简体   繁体   中英

Haskell Polymorphic definition

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:

  • doubt1: The reason for making the foldr types to be more general than fold.
  • doubt2: why do i get an error namely infinitely unification type.

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 ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM