Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I implement foldr for this particular structure?

Tags:

haskell

I am learning Haskell. I have a list that looks like this:

data TwoValueList a = Empty | Node a a (TwoValueList a)

I wish to make this Foldable, such that I might be able to do computations like:

sum (Node 0 1 (Node 2 3 Empty)) --should produce 6

If there were only one value, it would be easy:

data OneValueList = Empty | Node a (OneValueList a)
instance Foldable OneValueList where
  foldr f b Empty = b
  foldr f b (Node a rest) = f a (foldr f b rest)

However, if there are two values inside one node, I can't finegle the types because f takes a and b, but I must apply f to both as inside of the TwoValueList and combine them somehow. Am I missing some other type constraint?

Thank you.

like image 338
daikonradish Avatar asked Nov 14 '21 00:11

daikonradish


2 Answers

data TwoValueList a = Empty | Node a a (TwoValueList a)

instance Foldable TwoValueList where
  foldr _ ini Empty = ini
  foldr f ini (Node x y xs) = f x $ f y $ foldr f ini xs

The way this works is that foldr calls itself recursively on recursive instances of TwoValueList that are embeded in each other up until it meets Empty. At that point it returns ini which is the initial value and the call stack comes up resolving all the function calls further above.

like image 141
user1984 Avatar answered Sep 20 '22 13:09

user1984


I find it easier to just define the foldMap method instead:

data TwoValueList a = Empty | Node a a (TwoValueList a)

instance Foldable TwoValueList where
  foldMap _ Empty = mempty
  foldMap f (Node x y r) = f x <> f y <> foldMap f r
like image 20
dfeuer Avatar answered Sep 20 '22 13:09

dfeuer