该代码在Haskell中有效:
x a = (a + 1, a + 2)
x 2 -- returns (3, 4)
Run Code Online (Sandbox Code Playgroud)
而这不是:
x = ((+1), (+2))
<interactive>:935:1: error:
* Couldn't match expected type `Integer -> t'
with actual type `(Integer -> Integer, Integer -> Integer)'
* The function `x' is applied to one argument,
but its type `(Integer -> Integer, Integer -> Integer)' has none
In the expression: x 2
In an equation for `it': it = x 2
* Relevant bindings include it :: t (bound at <interactive>:935:1)
Run Code Online (Sandbox Code Playgroud)
有人可以解释我为什么吗?
错误的这一部分说明了其要点:
该函数
x应用于一个参数,但其类型(Integer -> Integer, Integer -> Integer)没有参数
当您编写无点函数时,您以这样的方式编写该函数:在表达式后给定更多参数,它将求出所需的结果。例如:
x a = 1 + a
-- same as:
x' = (1+)
-- because when you use it:
x 3 == 1 + 3 == 4
x' 3 == (1+) 3 == 4
Run Code Online (Sandbox Code Playgroud)
编写元组函数的方式并非如此,因为Haskell不知道您希望将函数元组用作函数。
x a = (1 + a, 2 + a)
-- not the same as:
x' = ((1+), (2+))
-- because:
x 1 == (1 + 1, 2 + 1) == (2, 3)
x' 1 == ((1+), (2+)) 1 == ???
Run Code Online (Sandbox Code Playgroud)
您可以检查pointfree.io,它将功能转换为:
x = liftM2 (,) (1 +) (2 +)
Run Code Online (Sandbox Code Playgroud)
它使用了元组是monad的事实(在另一个答案中有更好的描述),但可以说可读性较低。
您在这里构造的是一个2元组,其中每个元素都是一个函数。就这些。2元组不是函数,因此您不能只使用它并对其应用参数。
您可以在这里利用函数是Applicative实例的事实,从而可以使用:
x :: Num a => a -> (a, a)
x = (,) <$> (1+) <*> (2+)Run Code Online (Sandbox Code Playgroud)
或使用liftA2which做相同的事情:
import Control.Applicative(liftA2)
x :: Num a => a -> (a, a)
x = liftA2 (,) (1+) (2+)Run Code Online (Sandbox Code Playgroud)