Haskell 谁能解释这个哈斯克尔难题?

Haskell 谁能解释这个哈斯克尔难题?,haskell,Haskell,我知道,使用。运算符链一起起作用,如下所示: isLessThanZero x | x < 0 = True | otherwise = False (isLessThanZero . negate) 3 -- Produces True 但如果我要做的事情是: (subtract . negate) 1 2 -- 3 negate $ subtract 1 2 -- -1 这里的结果是不同的,这没有意义,因为这两个函数接受不同数量的参数。使用时,否定函数检查数字是否为

我知道,使用。运算符链一起起作用,如下所示:

isLessThanZero x 
   | x < 0 = True
   | otherwise = False

(isLessThanZero . negate) 3 -- Produces True
但如果我要做的事情是:

(subtract . negate) 1 2 -- 3
negate $ subtract 1 2 -- -1
这里的结果是不同的,这没有意义,因为这两个函数接受不同数量的参数。使用
时,
否定
函数检查数字是否为负数,但提供了两个参数。这可能意味着表达式是左关联的

negate (subtract 1 2) -- -1
(subtract . negate) 1 2 -- 3
但这令人困惑,因为在第一个示例中:

(isLessThanZero . negate) 3
表达式生成
True
,这意味着首先执行函数
negate
,然后调用
isLessThanZero
。但在最新的示例中,似乎首先调用了
subtract
,然后调用了
negate
。所以我不确定这里发生了什么。但更令人困惑的是:

subtract 1 2 -- Produces 1!
这意味着整个表达式:

(subtract . negate) 1 2 -- Produces 3!
是使用函数链接的副作用

我的理论是这样分解的:

我们知道2-(-1)=3。所以,表达式仍然是正确的。。我想
negate
仍然像上一个示例一样首先调用,只是它影响第一个参数,而不是两个参数,这是有意义的,因为negate只接受一个参数,并且我们根本不映射函数


那么,当涉及到用不同数量的参数链接函数时,Haskell应该如何应对呢?

在Haskell上,函数是curried的,所以:

f :: a -> b -> c
同:

f :: a -> (b -> c)
因此,在计算
F12
时,首先将
a
应用于
f
,得到类型为
b->c
的函数。然后应用
b
,得到
c

现在,让我们遵循以下类型:

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

Prelude> :t negate
negate :: Num a => a -> a

Prelude> :t subtract
subtract :: Num a => a -> a -> a

Prelude> :t (subtract.negate)
(subtract.negate) :: Num b => b -> b -> b
那么,
(subtract.negate)2的类型是什么

Prelude> :t (subtract.negate) 1
(subtract.negate) 1 :: Num b => b -> b
正如你所看到的,
negate
得到了一个
1
并给出了
-1
,但是
subtract
得到了
-1
,并给出了
Int->Int
。然后你把
2
应用到
Int->Int
上,得到
3


简而言之,
()
始终是右关联的,并采用
(b->c)
(a->b)
。唯一的棘手部分是,<代码> C <代码>本身可以是<代码>(D -> E)。

< P> Haskell方法是考虑所有函数作为一个参数,并返回一个值,即使对于具有多个参数的函数也是如此。

因此,
subtract
函数的签名为:

subtract :: Num a => a -> a -> a
(.) :: (y -> z) -> (x -> y) -> x -> z
也可以看到:

subtract :: Num a => a -> (a -> a)
接受一个数值参数并返回一个接受一个数值并返回一个数值的函数

考虑到
()
,其签名为:

subtract :: Num a => a -> a -> a
(.) :: (y -> z) -> (x -> y) -> x -> z
它有两个函数,一个函数返回一个函数

如果将其应用于
(subtract.negate)
,则具有以下签名:

(subtract . negate) :: Num a => (a -> (a -> a)) -> (a -> a) -> (a -> (a -> a))
其中:

x = a
y = a
z = a -> a
此函数的签名是完全有效的

请注意,
subtract 12
的作用类似于
2-1

(subtract.negate)
函数是一个取一个数值的函数,对其求反并返回一个取另一个数值的函数,该数值将从中减去被求反的数值

还要注意,
否定(减去12)
等于
-1
,而不是
3

这可能意味着表达式是左关联的

negate (subtract 1 2) -- -1
(subtract . negate) 1 2 -- 3
我不明白你说的“少联想”是什么意思


函数应用程序是左关联的,这意味着
abc
解析为
(ab)c

组合的定义如下:
(a.b)c=a(bc)

因此

另一个表达式是这样的(带有
a$b=ab
):


那么,函数组合和函数应用程序是否都是右关联的(从右到左)?对于
来说,这并不重要,因为
是一个。(b.c)=(a.b)。c
$
是右关联的,因为
a$b$c
解析为
a$(b$c)
。您可以在GHCi:
:i中找到具有
:i的任何运算符的关联性和优先级。
返回
[…]infixr 9.