我知道使用了。运算符链一起运行,如下所示:
isLessThanZero x
| x < 0 = True
| otherwise = False
(isLessThanZero . negate) 3 -- Produces True
或者使用$:
getNegNumbers x = map (*x) [-1, -2, -3]
filter isLessThanZero $ getNegNumbers 2 -- Produces [-2, -4, -6]
但是,如果我做的事情如下:
(subtract . negate) 1 2 -- 3
negate $ subtract 1 2 -- -1
这里的结果是不同的,它没有意义,因为这两个函数接受不同数量的参数。使用.
negate
函数检查数字是否为负数,但提供了两个参数。这可能意味着表达式是左关联的。
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应该如何回应呢?
答案 0 :(得分:4)
在Haskell上,函数是curry,所以:
group by
与:
相同f :: a -> b -> c
因此,当您计算f :: a -> (b -> c)
时,您首先将f 1 2
应用于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
。
答案 1 :(得分:4)
Haskell方法是将所有函数视为接受一个参数并返回一个值,即使对于具有多个参数的函数也是如此。
因此,subtract
函数的签名为:
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 1 2
的行为与2 - 1
类似。
(subtract . negate)
函数是一个函数,它接受一个数值,否定它并返回一个函数,该函数取另一个数值,从中减去否定值。
另请注意,negate (subtract 1 2)
等于-1
,而不是3
!
答案 2 :(得分:2)
这可能意味着表达式是左关联的。
我不明白你的意思是“少关联”。
函数应用程序是左关联的,意味着a b c
解析为(a b) c
。
组合定义如下:(a . b) c = a (b c)
。
因此
(subtract . negate) 1 2
= -- function application associates to the left
((subtract . negate) 1) 2
= -- definition of composition
(subtract (negate 1)) 2
= -- definition of subtract
2 - (negate 1)
= -- definition of negate
2 - (-1)
= -- definition of -
3
另一个表达式是这样的(带有a $ b = a b
):
negate $ subtract 1 2
= -- function application has higher precedence than any operator
negate $ (subtract 1 2)
= -- definition of $
negate (subtract 1 2)
= -- definition of negate
-(subtract 1 2)
= -- definition of subtract
-1