Lambda Jam 2018-05-22 Amy Wong

Lambda Jam 2018-05-22 Amy Wong

Introduction to Recursion schemes Lambda Jam 2018-05-22 Amy Wong BRICKX [email protected] Agenda • My background • Problem in recursion • Fix point concept • Recursion patterns, aka morphisms • Using morphisms to solve different recursion problems • References of further reading • Q & A My background • Scala developer • Basic Haskell knowledge • Not familiar with Category Theory • Interested in Functional Programming Recursion is ubiquitous, however, recusive calls are also repeatedly made Example 1 - expression data Expr = Const Int | Add Expr Expr | Mul Expr Expr eval :: Expr -> Int eval (Const x) = x eval (Add e1 e2) = eval e1 + eval e2 eval (Mul e1 e2) = eval e1 * eval e2 Evaluate expression > e = Mul ( Mul (Add (Const 3) (Const 0)) (Add (Const 3) (Const 2)) ) (Const 3) > eval e > 45 Example 2 - factorial factorial :: Int -> Int factorial n | n < 1 = 1 | otherwise = n * factorial (n - 1) > factorial 6 > 720 Example 3 - merge sort mergeSort :: Ord a => [a] -> [a] mergeSort = uncurry merge . splitList where splitList xs | length xs < 2 = (xs, []) | otherwise = join (***) mergeSort . splitAt (length xs `div` 2) $ xs > mergeSort [1,2,3,3,2,1,-10] > [-10,1,1,2,2,3,3] Problem • Recursive call repeatedly made and mix with the application-specific logic • Factoring out the recursive call makes the solution simpler Factor out recursion • Recursion is iteration of nested structures • If we identify abstraction of nested structure • Iteration on abstraction is factored out as pattern • We only need to define non-recursive function for application requirement • Problem solved in simple way How? Fix point Higher-kinded type Fix, (* -> *) -> * newtype Fix f = Fix { unFix :: f (Fix f) } Fix f is nested data structure We expect f is not just a type constructor but also a functor Iterate Fix f newtype Fix f = Fix { unFix :: f (Fix f) } fmap iterate f (Fix f) f a unFix alg iterate Fix f a Replace iterate by cata alg Decouples alg from recursion pattern fmap (cata alg) f (Fix f) f a unFix alg cata alg Fix f a cata function cata :: (Functor f) => (f a -> a) -> Fix f -> a cata alg = alg . fmap (cata alg) . unfix cata is called catamorphism - fundamental recursion pattern Highlights on catamorphism cata :: (Functor f) => (f a -> a) -> Fix f -> a alg :: f a -> a is called algebra, non-recursive function for application-specific logic a is called carrier of the algebra If we solve a recursion problem using cata, we only need to define functor f and f a -> a according to application requirement Catamorphism example - expression Original ADT data Expr = Const Int | Add Expr Expr | Mul Expr Expr Re-design the ADT as functor (notice the bolded carrier type) data ExprF a = Const Int | Add a a | Mul a a deriving Functor Algebra to evaluate expression -- cata :: (Functor f) => (f a -> a) -> Fix f -> a In evaluating an expression, carrier type is Int eval :: ExprF Int -> Int eval (Const c) = c eval (Add x y) = x + y eval (Mul x y) = x * y -- cata :: (Functor f) => (f a -> a) -> Fix f -> a > e = Fix $ Mul (Fix $ Mul (Fix $ Add (Fix $ Const 3) (Fix $ Const 0)) (Fix $ Add (Fix $ Const 3) (Fix $ Const 2)) ) (Fix $ Const 3) > cata eval e > 45 Algebra to format expression -- cata :: (Functor f) => (f a -> a) -> Fix f -> a In formatting an expression, carrier type is String format :: ExprF String -> String format (Const c) = show c format (Add s1 s2) = "(" <> s1 <> " + " <> s2 <> ")" format (Mul s1 s2) = s1 <> " * " <> s2 > cata format e > "(3 + 0) * (3 + 2) * 3" But catamorphism can’t solve all problems Anamorphism – opposite of Catamorphism • Catamorphism is building up a value from a nested structure, like a piece of paper folded up to an object • Anamorphism is the opposite, like an object unfolded to a piece of paper Anamorphism signature Catamorphism cata :: (Functor f) => (f a -> a) -> Fix f -> a cata alg = alg . fmap (cata alg) . unFix Anamorphism ana :: (Functor f) => (a -> f a) -> a -> Fix f ana coalg = Fix . fmap (ana coalg) . coalg coalg :: (a -> f a) is called coalgebra Hylomorphism The composition of anamorphism followed by catamorphism hylo :: (Functor f) =>(f b -> b) -> (a -> f a) -> a -> b hylo alg coalg = cata alg . ana coalg Alternatively, eliminating intermediate nested data structure hylo alg coalg = alg . fmap (hylo alg coalg) . coalg Hylomorphism example – merge sort Original code for merge sort mergeSort :: Ord a => [a] -> [a] mergeSort = uncurry merge . splitList where splitList xs | length xs < 2 = (xs, []) | otherwise = join (***) mergeSort . splitAt (length xs `div` 2) $ xs ADT for merge sort -- (notice that bolded carrier type) data TreeF a r = Empty | Leaf a | Branch r r deriving Functor Coalgebra for anamorphism -- ana :: (Functor f) => (a -> f a) -> a -> Fix f -- TreeF a is functor, [a] is carrier type split :: Ord a => [a] -> TreeF a [a] split [] = Empty split [x] = Leaf x split xs = uncurry Branch . splitAt (length xs `div` 2) $ xs Algebra for catamorphism -- cata :: (Functor f) => (f a -> a) -> Fix f -> a merge_ :: Ord a => TreeF a [a] -> [a] merge_ Empty = [] merge_ (Leaf x) = [x] merge_ (Branch l r) = merge l r -- hylo :: (Functor f) =>(f b -> b) -> (a -> f a) -> a -> b > hylo merge split [1,2,3,3,2,1,-10] > [-10,1,1,2,2,3,3] Paramorphism cata :: (Functor f) => (f a -> a) -> Fix f -> a In catamorphism, (f a -> a) only provides the value a, to be transformed. It doesn’t provide the original structure, Fix f from which the value is built. Paramorphism address this problem para :: (Functor f) =>(f (a, Fix f) -> a)-> Fix f -> a para alg = alg . fmap (para alg &&& id) . unFix Paramorphism example Original code for factorial factorial n | n < 1 = 1 | otherwise = n * factorial (n - 1) ADT for the natural number that copes with following conditions • Number < 1 • Number >= 1 data NatF a = Zero | Succ a deriving Functor Use Catamorphism for natural number -- cata :: (Functor f) => (f a -> a) -> Fix f -> a natAlg :: NatF Int -> Int natAlg Zero = 0 natAlg (Succ n) = n + 1 Use Paramorphism for factorial number --para :: (Functor f) => (f (a, Fix f) -> a) -> Fix f -> a factAlg :: NatF (Int, Fix NatF) -> Int factAlg Zero = 1 factAlg (Succ (n, x)) = n * cata natAlg (Fix $ Succ x) > nat = Fix $ Succ $ Fix $ Succ $ Fix $ Succ $ Fix Zero > para factAlg nat > 6 Recap Catamorphism cata :: (Functor f) => (f a -> a) -> Fix f -> a Anamorphism ana :: (Functor f) => (a -> f a) -> a -> Fix f Hylomorphism hylo :: (Functor f) =>(f b -> b) -> (a -> f a) -> a -> b Paramorphism para :: (Functor f) => (f (a, Fix f) -> a) -> Fix f -> a Recursion schemes • Catamorphism, paramorphism, anamorphism and hylomorphism are fundamental morphisms • They are available from Haskell recursion schemes library • When using morphisms to solve recursion problems, we only need to consider application-specific requirement by designing ADT for functor and non-recursive function More interesting morphisms • More interesting morphisms are available from recursion schemes library • More morphisms to be invented by us • Try to use morphisms to solve recursion problems to make simple solution References • https://www.schoolofhaskell.com/user/bartosz/understanding-algebras • http://blog.sumtypeofway.com/an-introduction-to-recursion-schemes/ • https://github.com/willtim/recursion-schemes/raw/master/slides-final.pdf - • http://hackage.haskell.org/package/recursion-schemes • http://maartenfokkinga.github.io/utwente/mmf91m.pdf - Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire • https://github.com/slamdata/matryoshka - recursion schemes in Scala Q & A.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    38 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us