答案 0 :(得分:3)
让我们从仿函数和适用法则开始。 Let's take a look at these laws presented in the Haskell Wikibook
fmap id = id -- 1st functor law
fmap (g . f) = fmap g . fmap f -- 2nd functor law
现在我们应该看看适用法律。
pure id <*> v = v -- Identity
pure f <*> pure x = pure (f x) -- Homomorphism
u <*> pure y = pure ($ y) <*> u -- Interchange
pure (.) <*> u <*> v <*> w = u <*> (v <*> w) -- Composition
身份法则认为应用
pure id
态射不会做任何事情,就像使用普通id
函数一样。同态定律表示将“纯”函数应用于“纯”值与将函数应用于正常方式的值然后在结果上使用纯值相同。从某种意义上说,这意味着纯粹的保留功能应用。
交换法规定,将态射应用于“纯”值
pure y
与将pure ($ y)
应用于态射相同。没有惊喜 - 正如我们在高阶函数章节中看到的那样,($ y)
是将y
作为参数提供给另一个函数的函数。组成法规定,
pure (.)
类似于(.)
组成函数的方式组成态射:将组合态射pure (.) <*> u <*> v
应用于w
会产生与应用{{1}相同的结果将u
应用于v
的结果。
Per @ benjamin-hodgson
足以证明
w
因适用法律而遵守fmap f x = pure f <*> x
法律。
我们只需要证明fmap id = id
遵守fmap f x = pure f <*> x
法律的原因是因为可以证明第二个仿函数法可以遵循第一定律。我已经简要介绍了这个证明,但Edward Kmett有一个更详细的版本here
Wadler Theorems for Free的第3.5节提供了关于函数fmap id = id
的一些工作。基于自由定理的思想,为函数显示的任何东西都适用于相同类型签名的任何其他函数。由于我们知道列表是仿函数,因此map
的类型类似于map :: (a -> b) -> [a] -> [b]
的类型,这意味着Wadler的所有地图也适用于fmap。
Wadler关于地图的结论导致了关于fmap的这个定理:
给定函数fmap :: Functor f => (a -> b) -> [a] -> [b]
,f
,g
和k
,h
然后g . h = k . f
$map g . fmap h = fmap k . $map' f
为$map
给定仿函数的“自然”映射函数。这个定理的完整证明有点冗长,但Bartosz Milewski提供了一个很好的overview。
我们需要两个引理来证明第二个仿函数法是第一个的结果。
给定fmap id = id --the first functor law
然后fmap f = $map f
fmap f = $map id . fmap f --Because $map id = id
= fmap id . $map f --Because of the free theorem with g = k = id and h = f
= $map f --Because of the first functor law
所以fmap f = $map f
和fmap = $map
f . g = id . (f . g)
, id . v = v
显而易见
给定fmap id = id
然后fmap f . fmap g = fmap (f . g)
fmap f . fmap g = $map f . fmap g --Because of lemma 1
= fmap id . $map (f . g) --Because of the free theorem for fmap and lemma 2
= $map (f . g) --Because of the first functor law
= fmap (f . g) --Because $map = fmap
因此,如果我们能够证明第一个仿函法是有效的,那么第二个也将成立。
表明我们需要适用身份法。看看法律,我们pure id <*> v = v
,并从我们试图证明的等价f <$> x = pure f <*> x
。如果我们让x = id
那么应用身份法告诉我们,等效的右边是id x
,第一个Functor法则告诉我们左边是id x
。
f <$> x = pure f <*> x
id <$> x = pure id <*> x -- Substitute id into the general form
id <$> x = x -- Apply the applicative identity law
id x = x -- Apply the first functor law
x = x -- simplify id x to x
我们已经证明fmap f x = pure f <*> x
通过适用法律遵守第一个仿函数法。