Skip to content

Instantly share code, notes, and snippets.

@CMCDragonkai
Last active May 2, 2018 21:31
Show Gist options
  • Save CMCDragonkai/b586ee9ecce297ceeeb3 to your computer and use it in GitHub Desktop.
Save CMCDragonkai/b586ee9ecce297ceeeb3 to your computer and use it in GitHub Desktop.
Haskell: Unfold Anamorphism, the opposite of fold/reduce, it takes a seed and generators a large value
-- just to differentiate a finite data list vs an infinite codata list
-- list in Haskell is actually a codata, but it can be data
-- in this way we know when we talk about Stream we're meaning codata
type Stream a = [a]
-- take a generator, a seed, and return an infinite Stream (codata list)
-- I prefer using a name like "explode" or "blossom" or "spread" rather than "unfold"
unfold :: (b -> (a, b)) -> b -> Stream a
unfold f b =
let (a, b') = f b
in a : unfold f b'
-- a convenient function to produce a product from 2 functions
-- it's called a fork, because it results in a pair forming function
-- x -> (a, b) (thus forking x to a and b)
fork :: (x -> a, x -> b) -> x -> (a, b)
fork (f, g) a = (f a, g a)
-- mapping infinite lists
mapS :: (a -> b) -> Stream a -> Stream b
mapS f =
let generator = fork (f . head, tail)
in unfold generator
-- the generator must generate a product of a value and the next seed
generator a = (a, a + 1)
-- lazy evaluation allows us to store their expressions, not the value (which
-- would be infinitely large)
x = unfold generator 0
-- we can do computations on the infinite list, like mapping the infinite list
y = mapS (+ 1) x
main = do
print "x"
print $ head x
print $ head . tail $ x
print $ head . tail . tail $ x
print "y"
print $ head y
print $ head . tail $ y
print $ head . tail . tail $ y
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment