函数组合错误

时间:2017-11-15 03:29:05

标签: haskell

我正在学习Haskell,但我遇到的情况是,我并不完全确定发生了什么。

我正在开展一个更大的项目,并一直在努力简化'我的代码。我已经了解了功能构成,我想我大多都了解它。然而,在突破极限的同时,我遇到了一种我不确定如何解释的情况。

经过几个小时的摆弄之后,我把它煮成了这个:

foo1 x y z = x == (y && z)
foo2 x y z = (x ==) . (&&) y z     -- Error
foo3 x y   = (x ==) . (&&) y
foo4 x     = (x ==) . (&&)         -- Error

为什么foo1foo3有效,而foo2foo4在我尝试定义时会出错?据我所知,没有理由在输入和输出中添加或删除等效参数应该改变函数。

修改:包含错误

foo2会产生错误:

<interactive>:1:23: error:
    • Couldn't match expected type ‘a -> a1’ with actual type ‘Bool’
    • Possible cause: ‘(&&)’ is applied to too many arguments
      In the second argument of ‘(.)’, namely ‘(&&) y z’
      In the expression: (x ==) . (&&) y z
      In an equation for ‘foo2’: foo2 x y z = (x ==) . (&&) y z
    • Relevant bindings include
        x :: a1 (bound at <interactive>:1:6)
        foo2 :: a1 -> Bool -> Bool -> a -> Bool
          (bound at <interactive>:1:1)

虽然foo4给出错误:

<interactive>:2:15: error:
    • No instance for (Eq (Bool -> Bool))
        arising from an operator section
        (maybe you haven't applied a function to enough arguments?)
    • In the first argument of ‘(.)’, namely ‘(x ==)’
      In the expression: (x ==) . (&&)
      In an equation for ‘foo4’: foo4 x = (x ==) . (&&)

1 个答案:

答案 0 :(得分:2)

功能应用

让我们从功能应用开始。

a b是将函数a应用于一个参数b。

a b c是将函数a应用于两个参数b和c。

a b c d是函数a对三个参数b,c和d的应用。

(&amp;&amp;)和(。)的类型签名

然后看看这两个函数的类型签名。

(&&) :: Bool -> Bool -> Bool

有两个参数

(.) :: (b -> c) -> (a -> b) -> a -> c

有三个参数,其中两个是函数

然后我们研究这四种情况。

foo1

foo1 x y z = x == (y && z)

(y&amp;&amp; z)是(&amp;&amp;)y z,完全应用。所以结果是Bool类型。

x ==布尔是(==)x布尔。所以x是Bool类型。

有效。

foo2的

foo2 x y z = (x ==) . (&&) y z

(x ==)是一个需要一个参数的函数。

所以(x ==) . :: (a -> b) -> a -> c

然而,正如@Carcigenicate所说,你的(&amp;&amp;)已完全应用。

因此,编译器说,“无法将预期类型'a - &gt; a1'与实际类型'Bool'匹配”

foo3

foo3 x y   = (x ==) . (&&) y

(.) :: (b -> c) -> (a -> b) -> a -> c

(。)函数组合需要函数(x ==)和(&amp;&amp;)y

现在需要的只是另一个产生c。

所以foo3只是foo1的无点风格。

它也有效。

foo4

foo4 x     = (x ==) . (&&)

所以我们已经见面了(x ==)。

其类型签名是(a - &gt; b) - &gt; a - &gt; ç

然而,(&amp;&amp;):: Bool - &gt;布尔 - &gt;布尔

虽然它可以被视为Bool - &gt; (Bool - &gt; Bool),一个函数,它接受一个参数并产生一个Bool - &gt; Bool功能。

(Bool-> Bool)不是Eq的实例。它没有(==)。

因此编译器说“没有实例(Eq(Bool - &gt; Bool))”

无点样式

  

据我所知,没有理由添加或删除等价物   输入和输出的参数应该改变函数。

当它们处于同一水平时,它仍然适用。

名称b c d =功能b c ddfullyly

name b c = function b c - 等待一个参数

name b = function b - 等待两个参数

name = function - 等待三个/所有参数

但是函数组合需要将两个单参数函数组合成一个参数函数(正确的一个输出类型需要匹配左一个输入类型。)

所以顺序首先是函数应用,然后是(。)/函数组合第二。并且您需要将(b-> c)和(a-> b)馈送到(。)以获得新的(a-&gt; c)函数。