Skip to content

Instantly share code, notes, and snippets.

@robrix
Created June 29, 2017 14:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robrix/3ecbf3da4b48f6deac9f5b8520d07f68 to your computer and use it in GitHub Desktop.
Save robrix/3ecbf3da4b48f6deac9f5b8520d07f68 to your computer and use it in GitHub Desktop.
Functions defined with fix are more composable than directly recursive functions
module ParameterizedRecursion where
import Data.Function
-- A recursive function…
showTable :: (Show a, Show b) => [(a, b)] -> String
showTable ((a, b) : rest) = show a ++ " | " ++ show b ++ "\n" ++ showTable rest
showTable [] = ""
-- …can be defined instead as a fixpoint…
showTableFix :: (Show a, Show b) => [(a, b)] -> String
showTableFix = fix showTableNonRec
-- …of a nonrecursive function…
showTableNonRec :: (Show a, Show b) => ([(a, b)] -> String) -> [(a, b)] -> String
showTableNonRec recur ((a, b) : rest) = show a ++ " | " ++ show b ++ "\n" ++ recur rest
showTableNonRec _ [] = ""
-- …which we can use to vary the behaviour arbitrarily at any iteration…
showTableN :: (Show a, Show b) => Int -> [(a, b)] -> String
showTableN 0 = const ""
showTableN n = showTableNonRec (showTableN (pred n))
-- …or even write as combinators encoding these variations…
nThenDefault :: ((a -> b) -> a -> b) -> b -> Int -> a -> b
nThenDefault f defaultB = go
where go 0 = const defaultB
go n = f (go (pred n))
-- …which we then compose with the nonrecursive function.
showTableNComposed :: (Show a, Show b) => Int -> [(a, b)] -> String
showTableNComposed = nThenDefault showTableNonRec ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment