又一种无限类型的错误

时间:2017-09-22 05:09:56

标签: haskell

我正在尝试创建一个函数,该函数使用带有多个参数的函数g组合函数f。

c :: (a -> b) -> (c -> a) -> c -> b
c x y z = x(y(z))
lift = c c

(lift $ lift $ lift ... c)创建所需的功能:

*Main> (lift $ lift $ lift $ lift $ lift $ c) (\x -> x+2) (\x y z a b c -> x*y*z-(a*b*c)) 1 2 3 4 5 6
-112

但是,当我尝试定义一个函数来生成一个带有f,g,然后是n个参数的函数(为了保存输入),会发生以下错误:

cn 1 = c
cn k = lift (cn(k-1))
<interactive>:9:1: error:
    * Occurs check: cannot construct the infinite type: a ~ c0 -> a
      Expected type: t -> (a -> b) -> a -> b
        Actual type: t -> (a -> b) -> (c0 -> a) -> c0 -> b
    * Relevant bindings include
        cn :: t -> (a -> b) -> a -> b (bound at <interactive>:9:1)

为什么会出现此错误,我该如何解决?

1 个答案:

答案 0 :(得分:2)

如果没有类型类,你不能在Haskell中创建多变量函数。

当您尝试创建一个带有一个或两个参数的函数时,您尝试创建类型为a -> ba -> p -> b的函数。因此,编译器必须推断类型b等同于p -> b,因此函数的类型变为a -> p -> p -> p -> ...。换句话说,是一种无限型。

尝试创建此功能时会出现类似问题。第一行很好:

cn 1 = c

这意味着cn :: Int -> (b -> c) -> (a -> b) -> a -> c之类的东西。但是,我们现在在第二行遇到问题:

cn k = lift (cn (k-1))

由于我们知道cn :: Int -> (b -> c) -> (a -> b) -> a -> c,我们必须推断cn (k-1) :: (b -> c) -> (a -> b) -> a -> c。但是,从lift :: (x -> y -> z) -> x -> (w -> y) -> w -> z开始,我们看到返回值必须是(b -> c) -> (w -> a -> b) -> w -> c类型,它与原始类型声明冲突。

TL; DR:您无法通过值更改Haskell函数/值的类型。这意味着你不能在没有某些技巧的情况下编写多变量函数。