For the moment, the dream still goes on, at each haskell concept I learn I am more enticed. Yet I havent completely fulfilled working on this precious @luqui's answer to my previous question about catamorphism, and i'm gonna come back at it until it's ok. It was about this sample code on Wikipedia, dealing with catamorphism on BINARY trees.
Nonetheless, I have tried implementing catamorphism for NON BINARY trees but I face some troubles:
data Composition a = Leaf a
| Composite [Composition a]
data CompositionAlgebra a r = CompositionAlgebra { leaf :: a → r
, composite :: [r] → r }
foldComposition :: CompositionAlgebra a r → Composition a → r
foldComposition a@(CompositionAlgebra {leaf = f}) (Leaf x ) = f x
foldComposition a@(CompositionAlgebra {composite = g}) (Composite [y]) = map g [y]
-- that latest line doesnt please ghc upon "map g [y]"
maxOfPair :: a → a → a
maxOfPair x y = if( x > y) -- this doesnt please ghc either, Ordering trouble
then (x)
else (y)
maxInList :: [a] → a
maxInList (x:xs) = maxOfPair x (maxInList xs)
treeDepth :: CompositionAlgebra a Integer
treeDepth = CompositionAlgebra { leaf = const 1, composite = λx → 1 + maxInList x }
sumTree :: (Num a) ⇒ CompositionAlgebra a a
sumTree = CompositionAlgebra { leaf = id, composite = (+) }
-- and this lattest sumTree is wrong too for ghc
I see > and +, just like the C++ operators > and +. So I don't understand ghc is angry at me without my giving to it objets implementing opertor >/+ or not.
Secondly I must admit I'm completely hazy about the sense of => (different from -> ???) and @ which seems to be like a guide for pattern matching.
How would you correct this code ?
And a latest question, I am also trying doing this because the Composite Pattern happened to be the most important for me in C++. And obviously I see it can be almost described in only one/two line in Haskell (that is truely amazing for me).
But how would you haskell people express the fact that Leaf and Composite constructor of Composition may have some kind of the same Interface? (I know it's not the good word since data are not mutable, but I hope you can guess-understand my concern/goal)
this is the total compilation error;
src\Main.hs:27:79:
Couldn't match expected type `[r]'
against inferred type `Composition a'
In the expression: y
In the second argument of `map', namely `[y]'
In the expression: map g [y]
src\Main.hs:30:20:
Could not deduce (Ord a) from the context ()
arising from a use of `>' at src\Main.hs:30:20-24
Possible fix:
add (Ord a) to the context of the type signature for `maxOfPair'
In the expression: (x > y)
In the expression: if (x > y) then (x) else (y)
In the definition of `maxOfPair':
maxOfPair x y = if (x > y) then (x) else (y)
src\Main.hs:41:0:
Occurs check: cannot construct the infinite type: a = [a] -> [a]
When generalising the type(s) for `sumTree'
EDIT So this is the final version for non binary catamorphism
data Composant a = Leaf a
| Composite [Composant a]
data CompositionAlgebra a r = CompositionAlgebra { leaf :: a → r
, composite :: [r] → r }
foldComposition :: CompositionAlgebra a r → Composant a → r
foldComposition a@(CompositionAlgebra {leaf = f}) (Leaf x) = f x
foldComposition a@(CompositionAlgebra {composite = g}) (Composite ys) = g(map(foldComposition a) ys)
maxOfPair :: Ord a ⇒ a → a → a
maxOfPair x y = if( x > y)
then (x)
else (y)
maxInList :: Ord a => [a] → a
maxInList (x:xs) = maxOfPair x (maxInList xs)
treeDepth :: CompositionAlgebra a Integer
treeDepth = CompositionAlgebra { leaf = const 1, composite = λx → 1 + maxInList x }
addList :: Num a ⇒ [a] → a
addList (x:xs) = x + addList xs
sumTree :: (Num a) ⇒ CompositionAlgebra a a
sumTree = CompositionAlgebra { leaf = id, composite = addList }
And according to the valid answer below: what I was asking for haskell equivalent of C++ Interfaces contracts seems to be typeclasses constraints.
So the design pattern Composite would be achieved by applying typeclass constraints when constructing the Composition a. Maybe a new specialized data should be define. But I should learn typeclasses before doing that :-)