我要处理的任务如下:
pipe [f1,...,fn] x
应该返回f1(f2(...(fn x)))
这是我的代码:
pipe :: [(a -> a)] -> (a -> a)
pipe fs = foldl' f base fs
where
f a x = a (x)
base = (\x -> x)
我认为这在遍历函数列表时是有意义的,但是,编译器告诉我:
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.
我是Haskell的新手,感谢您的提前帮助:)
答案 0 :(得分:1)
你可以做
pipe :: [a -> a] -> (a -> a)
pipe = foldr (flip (.)) id
foldr
和foldl
之间是有区别的。
您的base
功能等效于id
。
在您的版本中,f
的定义不正确。它应该有两个函数并返回一个新函数。
您可以将其写为
pipe :: [(a -> a)] -> (a -> a)
pipe fs = foldl f id fs
where
f g h = g . h
base = (\x -> x)
或
pipe :: [(a -> a)] -> (a -> a)
pipe fs = foldl f id fs
where
f g h a = h (g a)
base = (\x -> x)
如果所有函数都是可交换的,则使用foldr
或foldl
没什么区别,否则您需要正确选择foldr
或foldl
。
答案 1 :(得分:0)
我将解释为什么您的代码无法正常工作。让我们计算pipe [g,h] x
。我们希望它是g(h x)
。
我将忽略类型,仅根据定义进行计算:
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
因此,在最后一行中,我们可以看到g
是用两个参数h
和x
调用的,而我们希望使用g (h x)
来代替。
错误是f
使用应用程序f a x = a x
而不是组合f a x = a . x
。使用后者,我们将得到
...
= ((base . g) . h) x
= base (g (h x))
= g (h x)