Guest User

Untitled

a guest
Oct 20th, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.30 KB | None | 0 0
  1. {-# Language ViewPatterns, GADTs, KindSignatures #-}
  2. import Data.List
  3.  
  4. {-
  5. catamorphisms: folds
  6. anamorphisms: unfolds
  7.  
  8. foldr vs foldl: foldl is almost never the right thing to use, use foldl' instead, which is a strict version
  9. (optimiser will do this for us)
  10. -}
  11.  
  12. foldr2 :: (a -> b -> b) -> b -> [a] -> b
  13. foldr2 f b [] = b
  14. foldr2 f b (h:t) = f h (foldr2 f b t)
  15.  
  16. -- easy to visualise with the list tree: it replaces the cons nodes (:) with f and nil ([]) with b
  17.  
  18. foldr3 :: ((a, b) -> b, () -> b) -> [a] -> b
  19. foldr3 (f, b) [] = b ()
  20. foldr3 (f, b) (h:t) = f (h, foldr3 (f, b) t)
  21.  
  22. {-
  23. -- these two functions correspond to list type constructors:
  24. -- data List a = Cons a (List a) -- (a, b) -> b
  25. -- | Nil -- () -> b
  26.  
  27.  
  28. this view lets us generalise folds. What's the "shape" of list type?
  29. - 2 alternatives
  30. - in 1st, there are two values combined
  31. - in 2nd, empty
  32.  
  33. it's a sum of products.
  34. Products are modelled using tuples: (a, List a)
  35. Unions are modelled using Either, so:
  36.  
  37. type List' a = Either () (a, List' a)
  38.  
  39. 1:2:3:4:[]
  40. R (1, R(2, R(3, R(4, L ()))))
  41.  
  42. these two things are isomorphic.
  43.  
  44. -}
  45.  
  46. foldr4 :: (Either (a, b) () -> b) -> [a] -> b
  47. foldr4 f [] = f $ Right ()
  48. foldr4 f (h:t) = f $ Left (h, foldr4 f t)
  49.  
  50. -- a simple equivalence that lets us use a single function that combines the two cases above
  51.  
  52. -- aside: turning a pair of functions into function of Either:
  53.  
  54. pair2either :: (a -> c, b -> c) -> Either a b -> c
  55. pair2either (f, g) (Left a) = f a
  56. pair2either (f, g) (Right b) = g b
  57.  
  58. {-
  59. but why are we doing this? To generalise foldr to our own data type.
  60. All we need is generalise the type of the function; we should always be able to represent the shape of our ADT
  61. as Eithers and pairs, and then have appropriate cases
  62.  
  63. if we have multiple data constructors -> nest eithers
  64. if we have more than two types in a product -> nest pairs
  65.  
  66.  
  67. But this is not all; we can unfold lists:
  68. -}
  69.  
  70. stars :: Int -> String
  71. stars = unfoldr go
  72. where
  73. go :: Int -> Maybe (Char, Int)
  74. go 0 = Nothing
  75. go n = Just ('*', n - 1)
  76.  
  77. -- this can be generalised as well by switching to paris and eithers!
  78.  
  79. unfoldr2 :: (b -> Either (a, b) ()) -> b -> [a]
  80. unfoldr2 f (f -> Right ()) = []
  81. unfoldr2 f (f -> Left (h, unfoldr2 f -> t)) = (h:t)
  82.  
  83. {-
  84. (this uses view pattern: f -> x says that before pattern matching we apply f to x and pattern match on the result)
  85. note that this is the inverse of foldr4
  86.  
  87. -}
  88.  
  89. stars2 :: Int -> String
  90. stars2 = unfoldr2 go
  91. where
  92. go :: Int -> Either (Char, Int) ()
  93. go 0 = Right ()
  94. go n = Left ('*', n - 1)
  95.  
  96.  
  97. -- if we don't care too much about that nice symmetry, we can rewrite unfoldr2 without view patterns:
  98.  
  99. unfoldr3 :: (b -> Either (a, b) ()) -> b -> [a]
  100. unfoldr3 f b = case f b of
  101. Right () -> []
  102. Left (h, b') -> case (unfoldr3 f b') of t -> (h:t)
  103.  
  104. {-
  105. Since there is no generalisation of Either to 3, 4 etc. we have to nest them, and it gets messy.
  106.  
  107. Can we write a general unfold that works for any data type? Idea:
  108.  
  109. -- X []
  110. -- X (:) :$ '*' :? (n - 1)
  111.  
  112. Lost? Let's try to explain, but first a quick demo of GADTs...
  113. -}
  114.  
  115. data List a = Nil | Cons a (List a)
  116.  
  117. data List2 :: * -> * where
  118. Nil2 :: List2 a
  119. Cons2 :: a -> List2 a -> List2 a
  120.  
  121. -- basically, GADTs provide more flexible, function-like syntax
  122.  
  123.  
  124. {-
  125.  
  126. data X :: * -> * where
  127. X :: a -> X a
  128. (:$) :: X (a -> b) -> a -> X b
  129. (:?) :: X (a -> b) -> s -> X b
  130.  
  131. Well, this is not gonna work, the (:?) is dodgy
  132.  
  133. let's try to work out what types we need:
  134. X (:) :: X (a -> ([a] -> [a]))
  135. X (:) :$ '*' :: X (String -> String)
  136. X (:) :$ '*' :? (n-1) :: X String
  137.  
  138. Hmm, we might need this:
  139. -}
  140.  
  141. data X :: * -> * -> * -> * where
  142. X :: a -> X c s a
  143. (:$) :: X c s (a -> b) -> a -> X c s b
  144. (:?) :: X c s (c -> b) -> s -> X c s b
  145.  
  146. {-
  147. s -- the seed (Int in our case)
  148. c -- the final type we are constructing (String)
  149.  
  150. now:
  151.  
  152. go :: Int -> X String Int String
  153. -}
  154.  
  155. {-
  156. Why don't we just do an ordinary anamorphism on an unfixed data type? Because we don't want to have to unfix our type!
  157.  
  158. So, we were defeated during the session, but look what Peter did on his train home:
  159. -}
  160.  
  161. unf :: forall s c . (s -> X c s c) -> s -> c
  162. unf f = go . f
  163. where
  164. go :: X c s b -> b
  165. go (X x) = x
  166. go (x :$ v) = go x v
  167. go (x :? s) = go x (unf f s)
  168.  
  169. stars3 :: Int -> String
  170. stars3 n = unf go n
  171. where
  172. go :: Int -> X String Int String
  173. go 0 = X []
  174. go n = X (:) :$ '*' :? (n - 1)
Add Comment
Please, Sign In to add comment