1

I have the DataType

data Rose a = Leaf a | Node [Rose a]

an example would be:

fmfp = Node [Node [Leaf "F"], Node [], Node [Leaf "F", Leaf "P"], Leaf "M"]

which graphically looks like this: enter image description here

I have learned how to (mechanically) write fold functions for different data types, and so I came up with this fold function:

foldRose :: (a -> r) -> ([r] -> r) -> Rose a -> r

foldRose fl fn Leaf a = fl a
foldRose fl fn Node a = fn (map (foldRose fl fn)) a

The thing is, I don't really understand WHAT it does. For example, if I had

foldRose id concat fmfp 

what would it do exactly? Would it be

foldRose id concat fmfp = concat [concat [id "F"], concat [], 
                                  concat [id "F", id "P"], id "M"]

How do you wrap your mind around those kinds of functions? What do they intuitively mean? Also, how do I write a mapRose function, what would I have to think befre starting, what would it be supposed to do?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
SavannahGemp
  • 405
  • 2
  • 9
  • 4
    "*Would it be …*" - yes, exactly that. Your intuition seems to be fine already. – Bergi Aug 14 '19 at 07:23
  • The output is thus `"FFPM"`, since you concatenate the labels. – Willem Van Onsem Aug 14 '19 at 07:54
  • how would I write a map, what's the thinking behind it, the important things to consider before starting? – SavannahGemp Aug 14 '19 at 08:03
  • 1
    A fold (AKA catamorphism) intuitively "replaces" each constructor with a user-provided function, and computes the resulting term. I think you understand that. From a higher viewpoint, it expresses the existence of the unique morphism between an initial F-algebra and any given F-algebra, but this can be hard to understand without a proper background. Still, you might want to read about `cata` from `recursion-schemes`, or [Bartosz Milewski's book](https://bartoszmilewski.com/2017/02/28/f-algebras/) if you want a deeper understanding. – chi Aug 14 '19 at 08:12
  • 2
    `mapRose f t` replaces every value `x :: a` in the tree `t :: Rose a` with `f x`. The result is then a `Rose b`, if `f :: a -> b`. GHC can even generate it for you (using `deriving Functor` and a few extensions), but writing it manually can be a nice exercise. – chi Aug 14 '19 at 08:15
  • mapRose f Leaf a = f a______ mapRose f Node t = foldRose f ?? t ______ what would be the function for a Node? – SavannahGemp Aug 14 '19 at 09:00

1 Answers1

1

Just follow the steps, slowly and confidently.

data Rose a = Leaf a | Node [Rose a]

fmfp = Node [ Node [Leaf "F"]
            , Node []
            , Node [Leaf "F", Leaf "P"]
            , Leaf "M" ]

foldRose :: 
         (a -> r)               -> 
               ([r] -> r)        -> 
                     Rose a       ->  r
foldRose fLeaf fNode (Leaf a    )  =  fLeaf a
foldRose fLeaf fNode (Node trees)  =  fNode (map (foldRose fLeaf fNode) trees)

("r" is for recursive result).

Notice that you had few errors there, which I fixed in the above. Now,

  foldRose id concat fmfp 
= let fLeaf = id
      fNode = concat
  in
  foldRose fLeaf fNode (Node [Node [Leaf "F"], Node [], Node [Leaf "F", Leaf "P"], Leaf "M"])
= fNode (map (foldRose fLeaf fNode) 
                             [Node [Leaf "F"], Node [], Node [Leaf "F", Leaf "P"], Leaf "M"])
= fNode [
          foldRose fLeaf fNode $ Node [Leaf "F"]
        , foldRose fLeaf fNode $ Node []
        , foldRose fLeaf fNode $ Node [Leaf "F", Leaf "P"]
        , foldRose fLeaf fNode $ Leaf "M" ]
= fNode [
          fNode $ map (foldRose fLeaf fNode) [Leaf "F"]
        , fNode $ map (foldRose fLeaf fNode) []
        , fNode $ map (foldRose fLeaf fNode) [Leaf "F", Leaf "P"]
        , fLeaf $ "M" ]
= fNode [
          fNode [ foldRose fLeaf fNode $ Leaf "F"]
        , fNode []
        , fNode [ foldRose fLeaf fNode $ Leaf "F", foldRose fLeaf fNode $ Leaf "P"]
        , fLeaf "M" ]
= fNode [
          fNode [ fLeaf "F"]
        , fNode []
        , fNode [ fLeaf "F", fLeaf "P"]
        , fLeaf "M" ]

and that is simply

= concat [ concat [ id "F"]
         , concat []
         , concat [ id "F", id "P"]
         , id "M"
         ]
= concat [ concat [ "F"], [], concat [ "F", "P"], "M" ]
= concat [          "F",               "FP",      "M" ]
Will Ness
  • 70,110
  • 9
  • 98
  • 181