Reputation: 74
The task I want to handle is described as below:
pipe [f1,...,fn] x
should returnf1(f2(...(fn x)))
Here is my code:
pipe :: [(a -> a)] -> (a -> a)
pipe fs = foldl' f base fs
where
f a x = a (x)
base = (\x -> x)
I think this makes sense as it iterates through the function list, however, the compiler tells me:
tutorial.hs:45:20: error:
• Occurs check: cannot construct the infinite type: a ~ a -> a
Expected type: (a -> a) -> (a -> a) -> a -> a
Actual type: ((a -> a) -> a -> a) -> (a -> a) -> a -> a
• In the first argument of ‘foldl'’, namely ‘f’
In the expression: foldl' f base fs
In an equation for ‘pipe’:
pipe fs
= foldl' f base fs
where
f a x = a (x)
base = (\ x -> x)
• Relevant bindings include
fs :: [a -> a] (bound at tutorial.hs:45:6)
pipe :: [a -> a] -> a -> a (bound at tutorial.hs:45:1)
|
45 | pipe fs = foldl' f base fs
| ^
Failed, no modules loaded.
I am a newcomer to Haskell, and Thanks for your help in advance:)
Upvotes: 1
Views: 451
Reputation: 479
You could do
pipe :: [a -> a] -> (a -> a)
pipe = foldr (flip (.)) id
There is a difference between foldr
and foldl
.
Your base
function is equivalent to id
.
In your version, the definition of f
is incorrect. It should take two functions and return a new function.
You could write it as
pipe :: [(a -> a)] -> (a -> a)
pipe fs = foldl f id fs
where
f g h = g . h
base = (\x -> x)
or
pipe :: [(a -> a)] -> (a -> a)
pipe fs = foldl f id fs
where
f g h a = h (g a)
base = (\x -> x)
If all functions are commutative, using foldr
or foldl
makes no difference, otherwise you need to choose foldr
or foldl
correctly.
Upvotes: 1
Reputation: 116139
I'll explain why your code is not working. Let's compute pipe [g,h] x
. We expect this to be g(h x)
.
I will ignore the types, and simply compute according to the definitions:
pipe [g,h] x
= foldl' f base [g,h] x
= foldl' f (f base g) [h] x
= foldl' f (f (f base g) h) [] x
= f (f base g) h x
= (f base g) h x
= base g h x
= g h x
So, in the last line we can see that g
is called with two arguments, h
and x
, while we expected to have g (h x)
instead.
The mistake is that f
uses application f a x = a x
instead of composition f a x = a . x
. Using the latter we would get
...
= ((base . g) . h) x
= base (g (h x))
= g (h x)
Upvotes: 0