进行检查:无法构造无限类型

时间:2018-09-29 03:27:02

标签: haskell types compiler-errors fold

我要处理的任务如下:

  

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的新手,感谢您的提前帮助:)

2 个答案:

答案 0 :(得分:1)

你可以做

pipe :: [a -> a] -> (a -> a)
pipe = foldr (flip (.)) id

foldrfoldl之间是有区别的。

您的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)

如果所有函数都是可交换的,则使用foldrfoldl没什么区别,否则您需要正确选择foldrfoldl

答案 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是用两个参数hx调用的,而我们希望使用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)