I'm trying to programme an in-order traversal of a binary tree in Haskell using a fold - which I've defined as:
foldB :: (x -> u -> u -> u) -> u -> BTree x -> u
foldB f a Nil = a
foldB f a (BNode x l r) = f x (foldB f a l) (foldB f a r)
I've defined an in-order traversal of a binary tree:
inorder :: Ord a => BTree a -> [a]
inorder Nil = []
inorder (BNode a x y) = inorder x ++ [a] ++ inorder y
But I can't seem to get them both to work together:
inorderFold :: Ord a => BTree a -> [a]
inorderFold = foldB inorder []
Related
listTree :: Tree a -> [a]
listTree = foldTree f z
where
f x y z = x + y + z
z = []
This is what I have so far, but my f is wrong because the expected type is Tree a -> [a] but the actual is Tree [a] -> [a]
data Tree a
= Tip
| Bin (Tree a) a (Tree a)
deriving (Show, Eq)
foldTree :: (b -> a -> b -> b) -> b -> Tree a -> b
foldTree f z Tip = z
foldTree f z (Bin l x r) = f (foldTree f z l) x (foldTree f z r)
This is fold and data type for tree.
Need help with defining f.
First of all, combining lists uses ++ in haskell. + is only used for adding numbers. Second, the variable y is of type a, not [a], so you cannot use ++ on it directly.
listTree :: Tree a -> [a]
listTree = foldTree f z
where
f x y z = x ++ [y] ++ z
z = []
I defined my own Data Type BinTree, which describes my binary trees:
data BinTree a = Empty | Node a (BinTree a) (BinTree a) deriving (Show,Eq)
After that I implemented three sort-functions for the binary trees: preorder, inorder and postorder:
preorder :: BinTree a -> [a]
preorder Empty = []
preorder (Node x lt rt) = [x] ++ preorder lt ++ preorder rt
inorder :: BinTree a -> [a]
inorder Empty = []
inorder (Node x lt rt) = inorder lt ++ [x] ++ inorder rt
postorder :: BinTree a -> [a]
postorder Empty = []
postorder (Node x lt rt) = postorder lt ++ postorder rt ++ [x]
To improve my order-functions, I implemented the foldTree function (which works as a normal foldr function, but with binary trees):
foldTree :: (a -> b -> b -> b) -> b -> BinTree -> b
foldTree f e Empty = e
foldTree f e (Node x lt rt) = f x (foldTree f e lt) (foldTree f e rt)
And now I got stuck, because I cant't figure out how to combine the order-functions with the foldTree.
Can someone give me a hint please?
If by "combine" you mean implement each of the three functions using the last one, then this my recent answer seems to be of use, e.g.
preorder t = foldTree (\a l r -> (a :) . l . r) id t []
inorder t = foldTree (\a l r -> l . (a :) . r) id t []
postorder t = foldTree (\a l r -> l . r . (a :)) id t []
Trying it out:
> t = Node 1 (Node 2 Empty (Node 3 Empty Empty)) (Node 4 (Node 5 Empty Empty) Empty)
{-
1
2 4
. 3 5 .
. . . .
-}
> inorder t
[2,3,1,5,4]
> preorder t
[1,2,3,4,5]
> postorder t
[3,2,5,4,1]
The correct type of your function is, of course,
foldTree :: (a -> b -> b -> b) -> b -> BinTree a -> b
-- ^^^
In recursion schemes, how can I construct something with type definition like (Recursive t, CoRecursive t) -> t -> ? -> t
I try to use recursion-schemes to update nodes. Taking list as an example, I can come up with two methods like:
update :: [a] -> Natural -> a -> [a]
update = para palg where
palg Nil _ _ = []
palg (Cons a (u, _)) 0 b = b : u
palg (Cons a (u, f)) n b = a : f (n-1) b
update' :: [a] -> Natural -> a -> [a]
update' = c2 (apo acoalg) where
c2 f a b c = f (a,b,c)
acoalg ([], _, _) = Nil
acoalg (_:as , 0, b) = Cons b $ Left as
acoalg (a:as , n, b) = Cons a $ Right (as, n-1, b)
However, these two implementations are good. In these two implementations, the constructor of ListF and [] appears in both sides of the equation. And the definition does not appear to be unique. Is there a better way to perform List update with recursion schemes?
Recursion schemes is flexible approach. You can also implement your own variant.
(Reuse cata)
zipo :: (Recursive g, Recursive h) => (Base g (h -> c) -> Base h h -> c) -> g -> h -> c
zipo alg = cata zalg
where
zalg x = alg x <<< project
update :: forall a. [a] -> Natural -> a -> [a]
update xs n a = zipo alg n xs
where
alg :: Maybe ([a] -> [a]) -> ListF a [a] -> [a]
alg _ Nil = []
alg Nothing (Cons y ys) = a:ys
alg (Just n') (Cons y ys) = y:(n' ys)
Also u can implement some parallel version like
zipCata :: (Recursive g, Recursive h) => ((g -> h -> r) -> Base g g -> Base h h -> r) -> g -> h -> r
zipCata phi x y = phi (zipCata phi) (project x) (project y)
update' :: forall a. [a] -> Natural -> a -> [a]
update' xs n a = zipCata alg n xs
where
alg :: (Natural -> [a] -> [a]) -> Maybe Natural -> ListF a [a] -> [a]
alg _ _ Nil = []
alg _ Nothing (Cons _ ys) = a:ys
alg f (Just n) (Cons y ys) = y:(f n ys)
Both variants (also as your) will be get the same result
PS. I hate approach for code sample on SO
I want to return the list of all the subtrees of the initial tree with the depth given in parameter
I've tried to return the list of the tree when the depth is 0 and when depth matching with n, I want to decrement n and apply the map function using my function and the n parameter decremented to the list of subtrees
data Tree t = Node t [Tree t] deriving (Show, Eq)
exTree :: Tree Int
exTree = Node 1 [ Node 2 [], Node 3 [ Node 4 [], Node 5 [],Node 6 []]]
height :: Tree t -> Int
height (Node _ []) = 1
height (Node _ l) = 1 + maximum (map height l)
treemap :: (t->t) -> Tree t -> Tree t
treemap f (Node x []) = Node (f x) []
treemap f (Node x l) = Node (f x) (map (treemap f) l)
-- Here is the function concerned:
extrForest :: Int -> Tree t -> [Tree t]
extrForest 0 a = [a]
extrForest n (Node _ l) = map (extrForest (n-1)) l
Here is the error message:
Couldn't match type ‘[Tree t]’ with ‘Tree t’
Expected type: Tree t -> Tree t
Actual type: Tree t -> [Tree t]
Relevant bindings include
l :: [Tree t] (bound at ds2.hs:16:22)
extrForest :: Int -> Tree t -> [Tree t] (bound at ds2.hs:15:1)
In the first argument of ‘map’, namely ‘(extrForest (n - 1))’
In the expression: map (extrForest (n - 1)) l
Still don't quite understand what you need, so here is a very ad-hoc solution.
Looking at your error, it is clear that you have the common problem [a] vs [[a]].
When you look at the type signature map :: (a -> b) -> [a] -> [b] you see that your function has to take an [a] and return a simple [b], not [[b]], as this then needs to be mapped over again. However, your extForest returns a list of forests, so what you should do, is to concatenate them: concat . map. Turns out this is a common thing, and there's a Prelude function to do this: concatMap :: Foldable t => (a -> [b]) -> t a -> [b].
An ADT can be represented using the Scott Encoding by replacing products by tuples and sums by matchers. For example:
data List a = Cons a (List a) | Nil
Can be encoded using the Scott Encoding as:
cons = (λ h t c n . c h t)
nil = (λ c n . n)
But I couldn't find how nested types can be encoded using SE:
data Tree a = Node (List (Tree a)) | Leaf a
How can it be done?
If the Wikipedia article is correct, then
data Tree a = Node (List (Tree a)) | Leaf a
has Scott encoding
node = λ a . λ node leaf . node a
leaf = λ a . λ node leaf . leaf a
It looks like the Scott encoding is indifferent to (nested) types. All it's concerned with is delivering the correct number of parameters to the constructors.
Scott encodings are basically representing a T by the type of its case expression. So for lists, we would define a case expression like so:
listCase :: List a -> r -> (a -> List a -> r) -> r
listCase [] n c = n
listCase (x:xs) n c = c x xs
this gives us an analogy like so:
case xs of { [] -> n ; (x:xs) -> c }
=
listCase xs n (\x xs -> c)
This gives a type
newtype List a = List { listCase :: r -> (a -> List a -> r) -> r }
The constructors are just the values that pick the appropriate branches:
nil :: List a
nil = List $ \n c -> n
cons :: a -> List a -> List a
cons x xs = List $ \n c -> c x xs
We can work backwards then, from a boring case expression, to the case function, to the type, for your trees:
case t of { Leaf x -> l ; Node xs -> n }
which should be roughly like
treeCase t (\x -> l) (\xs -> n)
So we get
treeCase :: Tree a -> (a -> r) -> (List (Tree a) -> r) -> r
treeCase (Leaf x) l n = l x
treeCase (Node xs) l n = n xs
newtype Tree a = Tree { treeCase :: (a -> r) -> (List (Tree a) -> r) -> r }
leaf :: a -> Tree a
leaf x = Tree $ \l n -> l x
node :: List (Tree a) -> Tree a
node xs = Tree $ \l n -> n xs
Scott encodings are very easy tho, because they're only case. Church encodings are folds, which are notoriously hard for nested types.