应用函子作为幺正函子

问题描述 投票:4回答:1

如针对Applicative Functors的Hackage中所提到的,它们是强大的松散幺半群仿函数。那么为什么他们在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
haskell applicative
1个回答
5
投票

正如你在回答的评论中提到的那样,join>>=也有类似的故事。当有几种语义等价的方法来定义某些东西时,最好总是选择最有效和务实的方式。 Haskell旨在编写代码,而不是为了证明事物(尽管如此,不幸的是Haskell仍然不会成为非常流行的编程语言)。

如果starAp有默认实现,几乎没有人会实现它(就像现在>>类型类中的Monad一样)。但<*>是非常有用的操作。它用于应用程序和monadic解析器(megaparsecattoparsecoptparse-applicative),我无法想象我的生活没有liftA*加入事物。并且这项操作尽可能高效非常重要。将starAp实现为fmap (uncurry ($)) (mult h x)可能会给编译器带来内联和优化的困难。

此外,使用Applicativemult操作来表示unit并不能真正解决任何问题。显然,mult = liftA2 (,)。但你的实施

mult (Just x) (Just y) = Just (x,y)

不完全正确。因为你的实现不够懒惰。您将评估这两种情况,只需评估一种情况就足够了。所以即使使用这个简单的功能你仍然会陷入困境。因此,这种表示严格地更糟。

© www.soinside.com 2019 - 2024. All rights reserved.