haskell-pointpoint两次捕获一个参数

bra*_*rka 1 haskell generator

该代码在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)

有人可以解释我为什么吗?

Aur*_*ílý 6

错误的这一部分说明了其要点:

该函数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的事实(在另一个答案中有更好的描述),但可以说可读性较低。

  • @bratpiorka`liftM2`(或/sf/answers/4118557621/中更通用的applicative-functor版本)在需要组合任意函数(例如,您作为参数接收)时非常有用。而不是可以构造自己的表情。片刻之后,您便习惯了该成语,并且可读性更强。 (2认同)

Wil*_*sem 5

您在这里构造的是一个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)