【问题标题】:What is the meaning of `pure x = (\_ -> x)`?`pure x = (\_ -> x)` 是什么意思?
【发布时间】:2018-05-03 07:04:20
【问题描述】:

我正在阅读 Applicative 的函数实例, 遇到了一行

instance Applicative ((->) r) where  
  pure x = (\_ -> x)  
  f <*> g = \x -> f x (g x)

语法我懂,但是第二行的意思不明白。

我的理解是:部分应用函数((-&gt;) r) 获取一个值并将该值包装到上下文中,其中包含始终返回该值的函数。

为什么它不只是通过将部分应用的函数应用于 x 来计算结果,然后才将结果存储在 Applicative 上下文中?

【问题讨论】:

  • 如果写成pure x r = x ; (f &lt;*&gt; g) r = (f r) (g r) 会更清楚,不是吗?

标签: haskell types semantics typeclass


【解决方案1】:

函数实例的pure(&lt;*&gt;)的签名是

pure :: a -> ((->) r a)  
(<*>) :: ((->) r (a -> b)) -> ((->) r a) -> ((->) r b)  

将 (->) 写为中缀运算符给出

pure :: a -> (r -> a)  
(<*>) :: (r -> (a -> b)) -> (r -> a) -> (r -> a)

所以pure是一个函数,它接受a类型的参数并返回一个接受r类型参数并返回a类型值的函数。
由于我们在写pure时无法知道r的类型,所以我们只能给出一个函数,返回给pure的参数。

【讨论】:

  • 能否提供使用纯函数实例的例子?
  • @Bulat M. pure 的函数实例基本上是const。所以你可以在相同的地方使用它(比如你可以使用pure而不是Just(:[])。使用pure而不是那些可以让你有可能制作更通用的代码(适用于任何应用程序的代码) ,而不是特定的实例)。
  • 请详细说明一个具体的例子,它允许编写更通用的代码。我会更容易理解。
  • 例如,考虑liftA2 f a b = pure f &lt;*&gt; a &lt;*&gt; b,它可以像liftA2 (+) (*3) (/6)这样的函数一样使用,这将使函数等效于\x -&gt; (x*3) + (x/6),因此我们可以将相同的参数应用于多个函数,然后以某种方式组合结果。另一个使用 liftA2 liftA2 (,) (^2) show 的例子,它将接受一个数字 a 创建一个带有正方形和字符串表示的元组。对于const 的用例,您可以查看this question 的答案