In this lecture about Haskell programming, there is a fold implementation, defined like so :
fold :: (a -> b -> b) -> b -> [a] -> b
fold f z [] = z
fold f z (x:xs) = f x (fold z f xs)
The idea is to use it to define sum, product, etc...
sum'' = fold (+) 0
product'' = fold (*) 1
length'' = fold addOne 0
where addOne _ s = 1 + s
There seems to be an inversion between z
and f
inside the recursion pattern: otherwise, how could z f xs
match (a -> b -> b) -> b -> [a]
?
In my opinion, the recursion pattern should be
fold f z (x:xs) = f x (fold f z xs)
However, shortly after in the lecture, you can find the following statement:
fold f z [a,b,c] = a `f` (b `f` (c `f` z))
This reinforces the so-called mistake, so I guess there must be a mistake in my head instead!
Shouldn't it be more like the following ?
fold f z [a,b,c] = `f` a (`f` b (`f` c z))
Am I missing a point, or is it a double mistake in the lecture?
There seems to be an inversion between
z
andf
inside the recursion pattern: otherwise how couldz f xs
match(a -> b -> b) -> b -> [a]
?
You're correct, the types don't align, and GHC is quick to let you know if you try to define fold
as given:
Couldn't match expected type ‘a -> b -> b’ with actual type ‘b’
‘b’ is a rigid type variable bound by
the type signature for fold :: (a -> b -> b) -> b -> [a] -> b
at test.hs:1:9
...
However, shortly after in the lecture, you can find the following statement:
fold f z [a,b,c] = a `f` (b `f` (c `f` z))
This reinforces the so-called mistake, so I guess there must be a mistake in my head instead!
Shouldn't it be more like the following ?
fold f z [a,b,c] = `f` a (`f` b (`f` c z))
No. Once you've defined fold
correctly, this unfolding of the definition is correct. The author is simply using the backtick notation to use function f
as an infix operator:
fold f z [a,b,c] = a `f` (b `f` (c `f` z))
is equivalent to
fold f z [a,b,c] = f a (f b (f c z))
but is perhaps more readable if you think of f
as binary function such as (+)
; compare
fold (+) 0 [1,2,3] = 1 + (2 + (3 + 0))
to the less readable
fold (+) 0 [1,2,3] = (+) 1 ((+) 2 ((+) 3 0))
The code fold f z (x:xs) = f x (fold z f xs)
should indeed be fold f z (x:xs) = f x (fold f z xs)
.
The second part is correct though, since (pay attention to the backticks)
f x y == x `f` y
we have
a `f` (b `f` (c `f` z)) == f a (f b (f c z)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With