应用函子作为幺半群函子
Applicative functors as monoidal functors
正如 Hackage for Applicative Functors 中提到的,它们是强松弛幺半群函子。那么为什么他们在 Haskell 中的定义没有这样显示:
class Functor f => MonoidalApplicative f where
mult :: f a -> f b -> f (a,b)
unit :: a -> f a
starAp :: f (a -> b) -> f a -> f b
starAp h x = fmap (uncurry ($)) (mult h x)
<*>
(starAp) 在乘法方面很容易重建,这个定义对我来说看起来更简单。例如,这里是 Maybe 实例:
instance MonoidalApplicative Maybe where
mult (Just x) (Just y) = Just (x,y)
mult _ _ = Nothing
unit x = Just x
正如在对您的回答的评论中提到的,join
和 >>=
也有类似的故事。当有几种语义上等效的方式来定义某物时,最好总是选择最有效和实用的方式。 Haskell 旨在编写代码,而不是为了证明事情(尽管不幸的是,不知何故 Haskell 仍未成为非常流行的编程语言)。
如果 starAp
有默认实现,几乎没有人会实现它(就像现在 Monad
中的 >>
键入 class 一样)。但是 <*>
是非常有用的操作。它在 applicate 和 monadic 解析器中使用了很多(megaparsec
、attoparsec
、optparse-applicative
),我无法想象我的生活 w/o liftA*
加入事物.此操作尽可能高效非常重要。将 starAp
实现为 fmap (uncurry ($)) (mult h x)
可能会给编译器的内联和优化带来困难。
此外,使用 mult
和 unit
操作表示 Applicative
并不能真正解决任何问题。显然,mult = liftA2 (,)
。但是你的实现
mult (Just x) (Just y) = Just (x,y)
不完全正确。因为你的实现不够懒惰。当仅评估一种情况可能就足够时,您将评估两种情况。所以即使是这个简单的函数,你仍然会搞砸。因此,这种表示形式更糟。
正如 Hackage for Applicative Functors 中提到的,它们是强松弛幺半群函子。那么为什么他们在 Haskell 中的定义没有这样显示:
class Functor f => MonoidalApplicative f where
mult :: f a -> f b -> f (a,b)
unit :: a -> f a
starAp :: f (a -> b) -> f a -> f b
starAp h x = fmap (uncurry ($)) (mult h x)
<*>
(starAp) 在乘法方面很容易重建,这个定义对我来说看起来更简单。例如,这里是 Maybe 实例:
instance MonoidalApplicative Maybe where
mult (Just x) (Just y) = Just (x,y)
mult _ _ = Nothing
unit x = Just x
正如在对您的回答的评论中提到的,join
和 >>=
也有类似的故事。当有几种语义上等效的方式来定义某物时,最好总是选择最有效和实用的方式。 Haskell 旨在编写代码,而不是为了证明事情(尽管不幸的是,不知何故 Haskell 仍未成为非常流行的编程语言)。
如果 starAp
有默认实现,几乎没有人会实现它(就像现在 Monad
中的 >>
键入 class 一样)。但是 <*>
是非常有用的操作。它在 applicate 和 monadic 解析器中使用了很多(megaparsec
、attoparsec
、optparse-applicative
),我无法想象我的生活 w/o liftA*
加入事物.此操作尽可能高效非常重要。将 starAp
实现为 fmap (uncurry ($)) (mult h x)
可能会给编译器的内联和优化带来困难。
此外,使用 mult
和 unit
操作表示 Applicative
并不能真正解决任何问题。显然,mult = liftA2 (,)
。但是你的实现
mult (Just x) (Just y) = Just (x,y)
不完全正确。因为你的实现不够懒惰。当仅评估一种情况可能就足够时,您将评估两种情况。所以即使是这个简单的函数,你仍然会搞砸。因此,这种表示形式更糟。