Reputation: 85
I am unable to understand the difference between fold
and foldr
.
The definition of fold
is:
fold :: (t->t->t) -> [t] -> t
fold f [a] = a
fold f (a:b:x)= f a (fold f (b:x))
where there is only one type-parameter t
foldr
is defined as
foldr :: (t->u->u) -> u -> [t] -> u
foldr f s [] = s
foldr f s (a:x) = f a (foldr f s x)
I am reading "The craft of functional programming" and it says the fold
function is modified by adding an extra argument for the purpose of checking for empty list. This doesn't make sense why there was a need for foldr
when the fold
function itself could have been modified to serve all the purposes.
Secondly,when I tried the following example from the book:
rev :: [t] -> [t]
rev list = foldr stick [] list
stick :: t -> [t] -> [t]
stick a x = x++[a]
and modified the definition of foldr
to foldr::(t->t->t)->[t]->t
. Hugs threw an error of inifinite unification type. I tried googling but could not find a satisfactory answer.
so to sum up my doubts are as follows:
foldr
types to be more general than fold.Upvotes: 0
Views: 93
Reputation: 52280
I'll start at the end:
rev :: [t] -> [t]
rev list = foldr stick [] list
stick :: t -> [t] -> [t]
stick a x = x ++ [a]
will work just fine if you use the definition of foldr
you gave:
foldr :: (t->u->u) -> u -> [t] -> u
foldr f s [] = s
foldr f s (a:x) = f a (foldr f s x)
as you can see here:
λ> rev [1..5]
[5,4,3,2,1]
what will not work is if you replace it with your definition of fold
:
fold :: (t->t->t) -> [t] -> t
no matter how you name it because the trouble start with the signature.
See - when you do rev list = fold stick [] list
then you say that
t -> t -> t
should somehow be equal to
t' -> [t'] -> [t']
as the first one is the type fold
expects for it's first argument and the second is the signature given by stick
(renamed t
to t'
here to indicate that the types should could be different).
Now this would mean that both t ~ t'
and t ~ [t']
or t ~ [t]
which is most likely the error you get (btw: a ~ b
here is me saying two types a
and b
should be equal - think =
if you like)
This should shed some light on your doubt2 I hope
now to the first part: To be honest I have no clue what I should tell you.
The reason to make fold
more general is that then it's more general - indeed foldr
is a very special function for lists - it is the list catamorphism (see also wikipedia)
But that's just complicated for general function to operate on lists
Indeed you can rewrite a huge number of functions on list (basically the recursive ones using patter-matching in the empty or cons style) with just foldr
- and this will very likely be a big part of your course (I think you are a student of FP101x right?) and of your book - as it's the example for higher-order-functions to rule them all ;)
Upvotes: 2