应用仿函数作为monoidal函子 [英] Applicative functors as monoidal functors
问题描述
class Functor f => MonoidalApplicative f其中
mult :: f a - > f b - > f(a,b)
unit :: a - > f a
starAp :: f(a - > b) - > f a - > fb
starAp hx = fmap(uncurry($))(mult hx)
< *>< / code>(starAp)在乘法方面很容易重建,这个定义对我来说更简单。举例来说,下面是Maybe实例:
pre $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ = Just(x,y)
mult _ _ = Nothing
unit x = Just x
$ b $ C $ C>>> = 。当有几种语义上相同的方法来定义某些东西时,最好总是选择最高效的&务实的方式。 Haskell被设计为编写代码,而不是用来证明事情(不过,不幸的是,Haskell 不幸仍然变得非常流行的编程语言)。
如果 starAp
具有默认实现,几乎没有人会实现它(就像现在在>>
中发生的 Monad
类型类)。但是<>
是非常有用的操作。它用于应用程序& monadic解析器很多( megaparsec
, attoparsec
, optparse-appative
),我无法想象我的生活将不需要 liftA *
来加入。此操作尽可能高效非常重要。将> starAp
实现为 fmap(uncurry($))(mult hx)
可能会给内联和优化带来困难编译器。
此外,使用 mult
和 mult = liftA2(,)
。但是,您的实现方式是使用
mult(Just x)(Just y)= Just(x,y)
不完全正确。因为你的实现不够懒惰。你会评估两种情况,当它可能足以评估一个。所以你甚至可以用这个简单的功能搞定。因此这种表示方式严重恶化。
As mentioned in Hackage for Applicative Functors, they are strong lax monoidal functors. So why doesn't their definition in Haskell show it like so :
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) is easily reconstructed in terms of the multiplication and this definition looks simpler to me. For exemple, here is the Maybe instance :
instance MonoidalApplicative Maybe where
mult (Just x) (Just y) = Just (x,y)
mult _ _ = Nothing
unit x = Just x
As it was mentioned in comments to your answer, there is similar story with join
and >>=
. When there're several semantically equivalent ways to define something it's better always to choose most efficient & pragmatic way. Haskell was designed to write code, not to prove things (though, somehow Haskell haven't still become very popular programming language unfortunately).
If starAp
had default implementation almost nobody would implement it (just as it happens now with >>
in Monad
type class). But <*>
is extremely useful operation. It is used in applicate & monadic parsers a lot (megaparsec
, attoparsec
, optparse-applicative
) and I can't imagine my life w/o liftA*
for joining things. And it is very important for this operation to be as efficient as possible. Implementing starAp
as fmap (uncurry ($)) (mult h x)
may bring hard times to inlining and optimizing things for compiler.
Moreover, representation of Applicative
using mult
and unit
operations doesn't really solves any problems. Obviously, mult = liftA2 (,)
. But your implementation with
mult (Just x) (Just y) = Just (x,y)
not fully correct. Because your implementation is not lazy enough. You will evaluate both cases when it may be enough to evaluate only one. So you still can fuck up even with this simple function. Thus this representation is strictly worse.
这篇关于应用仿函数作为monoidal函子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!