Haskell MaybeT m的应用实例假定为Monad m
我一直在使用Haskell MaybeT m的应用实例假定为Monad m,haskell,monads,monad-transformers,applicative,haxl,Haskell,Monads,Monad Transformers,Applicative,Haxl,我一直在使用Haxlmonad(这里描述:),它有一个有趣的特性,即它的应用实例的与Control.monad中的ap不同。这是一个关键特性,允许它在不阻塞的情况下进行并发计算。例如,如果hf和ha是长计算,那么 let hf :: Haxl (a -> b) = ... ha :: Haxl a = ... in do f <- hf a <- ha return (f a) 其中ap=liftM2 id来自Control.Monad。这使得 let h
Haxl
monad(这里描述:),它有一个有趣的特性,即它的应用实例的
与Control.monad中的ap
不同。这是一个关键特性,允许它在不阻塞的情况下进行并发计算。例如,如果hf
和ha
是长计算,那么
let hf :: Haxl (a -> b) = ...
ha :: Haxl a = ...
in do
f <- hf
a <- ha
return (f a)
其中ap=liftM2 id
来自Control.Monad
。这使得
let hmf :: MaybeT Haxl (a -> b) = ...
hma :: MaybeT Haxl a = ...
in hmf <*> hma
让hmf::MaybeT Haxl(a->b)=。。。
hma::MaybeT Haxl a=。。。
在hmf hma中
按顺序运行。看起来更好的例子应该是
instance (Applicative m) => Applicative (MaybeT m) where
pure = MaybeT . pure . Just
MaybeT f <*> MaybeT x = MaybeT $ (<*>) <$> f <*> x
instance(Applicative m)=>Applicative(MaybeT m)其中
纯=可能。纯净的只是
MaybeT f MaybeT x=MaybeT$()f x
(这里,右侧的()
代表Maybe
单子,而右侧的非括号
代表m
)请注意上下文是不同的——上面的实例只假设Applicative m
,而transformers中的实例假设Functor m,单子m
我的主要问题是实用的:对此我应该怎么做?我应该使用自己的MaybeT
monad transformer吗?如果我试着写上面的内容,ghc会向我抱怨“重复实例声明”,有什么办法可以避免吗
我还想知道:当前设置是否是transformers软件包中的一个设计缺陷?如果不是,为什么不呢?诀窍在于(与单子不同)应用程序函子是可组合的,因此您不需要(应用程序)转换器,例如MaybeT
。相反,您可以使用Compose
将两个应用程序函子组合在一起:
import Control.Applicative
import Data.Functor.Compose
type HaxlM = Compose Haxl Maybe
-- if you prefer to have a function for constructing values:
haxlM :: Haxl (Maybe a) -> HaxlM a
haxlM = Compose
合成始终是Applicative
的适当实例,并且仅使用其组件的Applicative
实例。例如:
test = getZipList . getCompose
$ (+) <$> Compose (ZipList [Just 1, Nothing, Just 3])
<*> Compose (ZipList [Nothing, Just 20, Just 30])
test=getZipList。getCompose
$(+)Compose(ZipList[Just 1,Nothing,Just 3])
撰写(ZipList[没有,只有20,只有30])
产生
[没有,没有,只有33]
每个人都倾向于假设超类实现与子类实现完全匹配。Haxl违反了这条不成文的规则,因此无法与他人友好相处。Transformers还假设您正在制作Monad
转换器,因此它的实现是这样的Applicative
“变压器”有更好的结构。@J.Abrahamson,这不是一条规则,不管是书面的还是其他的。这也不是唯一一个
在某些重要方面优于ap
的情况。在我看来,MaybeT
在这里是错误的。在作为GHC 7.10的一部分广泛传播之后,我们可以重写Applicative(MaybeT m)
定义。目前,Applicative
不是Monad
的超类,因此您可能会破坏许多包。此外,我还意外地看到许多Foo是Monad的实例,但仍然没有应用程序警告。建议您现在就编写自己的MaybeT
,或者对transformers
?进行公关。因为这往往是一条不成文的规则。人们通常认为您可以将do语法和()
语法转换为方便和美观的语法。一旦AMP登陆,这将更加强大,但也将很容易用applicative-only替换这个定义。事实上,这是一个书面规则–它就在Ok,cool中。但在这种情况下,我不能同时使用monad操作,对吗?(一般的Haxl计算同时使用applicative和monad来表示不同的数据流。)是否有某种方法可以充分利用这两个方面(例如,使用ap!=的HaxlM monad,而不必从头编写一个?@davidsd我想没有。你也许可以使用FlexibleInstances
/FlexibleContexts
为Compose-Haxl-Maybe
创建一个monad实例,但是最好还是从头开始创建HaxlM
monad。只要我们走在这条路上,值得注意的是,Applicative
产品也是Applicative
。与Applicative
求和相同,只要存在允许偏差工作的自然变换:
import Control.Applicative
import Data.Functor.Compose
type HaxlM = Compose Haxl Maybe
-- if you prefer to have a function for constructing values:
haxlM :: Haxl (Maybe a) -> HaxlM a
haxlM = Compose
test = getZipList . getCompose
$ (+) <$> Compose (ZipList [Just 1, Nothing, Just 3])
<*> Compose (ZipList [Nothing, Just 20, Just 30])