【发布时间】:2015-07-01 03:25:37
【问题描述】:
From the chapter on Functors in Learn You a Haskell for Great Good,Lipovača 说:
“当我们执行
(+) <$> (+3) <*> (*100)时,我们正在创建一个函数,它将在(+3)和(*100)的结果上使用+并返回它。为了演示一个真实的例子,当我们执行@987654326 时@,5首先被应用到(+3)和(*100),产生8和500。然后,+被8和500调用,产生508。 "
但是,如果我尝试自己评估函数,考虑到函子 ((->) r) 上的 Applicative 的这个定义:
instance Applicative ((->) r) where
pure x = (\_ -> x)
f <*> g = \x -> f x (g x)
我将上述表达式的评估读为:
(\x -> (3 + x) (100 * x)) $ 5
但我不明白我们如何将两个部分应用的二进制函数组合为一个 lambda(事实上,GHCi 会抛出一个无限类型错误,试图将它绑定到一个变量)。此外,根据工作解释,如果我们查看 <$> 的类型定义,我们会得到:
(<$>) :: Functor f => (a -> b) -> f a -> f b
或者更具体地说,我们可以将其提升视为:
(<$>) :: Functor f => (a -> b) -> (f a -> f b)
考虑到在这种情况下我们的函子是 ((->) r),我可以推断这就是在之前的评估中发生的转换(假设左关联首先发生,而不是 @987654341 的右关联应用@):
(\x -> a + b) 其中a = (+ 3) 和b = (* 100)。这是应该返回的函数。但是,我假设这是最终(粗略)形式是否正确?
(\x -> (3 + x) + (100 * x)) $ 5
...产生 508。
我发现 Lipovača 的描述在表达式如何工作方面更容易理解,但我的直觉告诉我,对于 Haskell 编译器引擎盖下的血腥细节来说,这并不完全正确。我更容易认为 (+) 的 fmap 首先发生导致具有两个函子的函数,这两个函子是接受共享输入的部分应用函数,然后我们对其应用了一个值。由于惰性评估,我们可以这样做。这是错的吗?
【问题讨论】:
标签: haskell functor applicative