Guest User

Untitled

a guest
Oct 21st, 2017
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.02 KB | None | 0 0
  1. {-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
  2. {-# LANGUAGE StandaloneDeriving, UndecidableInstances #-}
  3.  
  4. module Morphisms where
  5.  
  6. data Expr a = Const Int
  7. | Add a a
  8. | Sub a a
  9. | Mul a a
  10. | Div a a
  11. deriving (Show, Eq, Functor, Foldable, Traversable)
  12.  
  13. {-- equivalent to:
  14. instance Functor Expr where
  15. fmap _ (Const x) = Const x
  16. fmap f (Add x y) = Add (fmap f x) (fmap f y)
  17. fmap f (Sub x y) = Sub (fmap f x) (fmap f y)
  18. fmap f (Mul x y) = Mul (fmap f x) (fmap f y)
  19. fmap f (Div x y) = Div (fmap f x) (fmap f y)
  20. --}
  21.  
  22. newtype Term f = In { out :: f (Term f) }
  23.  
  24. -- this requires undecidableinstances
  25. deriving instance Show (f (Term f)) => Show (Term f)
  26.  
  27. bottomUp :: Functor a => (Term a -> Term a) -> Term a -> Term a
  28. bottomUp f = f . In . fmap (bottomUp f) . out
  29. -- bottomUp f t = f $ In $ fmap (bottomUp f) $ out t
  30.  
  31. topDown :: Functor a => (Term a -> Term a) -> Term a -> Term a
  32. topDown f = In . fmap (topDown f) . out . f
  33. -- topDown f t = In $ fmap (topDown f) $ out $ f t
  34.  
  35. example = In (Mul
  36. (In (Add
  37. (In (Const 7))
  38. (In (Const 9))))
  39. (In (Sub
  40. (In (Const 3))
  41. (In (Div (In (Const 9)) (In (Const 2)))))))
  42.  
  43. plusTwo = bottomUp f example where
  44. f (In (Const x)) = In $ Const $ x + 2
  45. f x = x
  46.  
  47. addMul = topDown f example where
  48. f (In (Add x y)) = In (Mul x y)
  49. f x = x
  50.  
  51. -- a generalized fold; like bottomUp but without the In
  52. foldy :: Functor f => (f a -> a) -> Term f -> a
  53. foldy f = f . fmap (foldy f) . out
  54.  
  55. countNodes :: Expr Int -> Int
  56. countNodes (Const _) = 1
  57. countNodes (Add x y) = 1 + x + y
  58. countNodes (Sub x y) = 1 + x + y
  59. countNodes (Mul x y) = 1 + x + y
  60. countNodes (Div x y) = 1 + x + y
  61.  
  62. countExample = foldy countNodes example
  63.  
  64. -- in the jargon, an f a -> a is an Algebra and foldy is a catamorphism
  65. -- cata == downwards/collapse
  66.  
  67. type Algebra f a = f a -> a
  68.  
  69. cata :: Functor f => Algebra f a -> Term f -> a
  70. cata f = f . fmap (cata f) . out
  71.  
  72. pp :: Expr String -> String
  73. pp (Const n) = show n
  74. pp (Add x y) = "(" ++ x ++ " + " ++ y ++ ")"
  75. pp (Sub x y) = "(" ++ x ++ " - " ++ y ++ ")"
  76. pp (Mul x y) = "(" ++ x ++ " x " ++ y ++ ")"
  77. pp (Div x y) = "(" ++ x ++ " / " ++ y ++ ")"
  78.  
  79. ppExample = cata pp example
  80.  
  81. -- n.b. bottomUp f == cata (f . In)
  82. bottomUp' :: Functor a => (Term a -> Term a) -> Term a -> Term a
  83. bottomUp' = cata . (. In)
  84.  
  85. plusTwo' = bottomUp' f example where
  86. f (In (Const x)) = In $ Const $ x + 2
  87. f x = x
  88.  
  89. -- a generalized unfold, like topDown without the out
  90. unfoldy :: Functor f => (a -> f a) -> a -> Term f
  91. unfoldy f = In . fmap (unfoldy f) . f
  92.  
  93. -- you guessed it: we flipped the arrows, so:
  94.  
  95. type CoAlgebra f a = a -> f a
  96.  
  97. -- ana = building
  98. ana :: Functor f => CoAlgebra f a -> a -> Term f
  99. ana f = In . fmap (ana f) . f
  100.  
  101. -- we need an extra bit of state for "expand me" vs "const me"
  102. makeFactorial :: Int -> Term Expr
  103. makeFactorial n = ana f (n, True) where
  104. f :: (Int, Bool) -> Expr (Int, Bool)
  105. f (0, _) = Const 1
  106. f (n, True) = Mul (n, False) (n - 1, True)
  107. f (n, False) = Const n
Add Comment
Please, Sign In to add comment