是否可以仅使用Applicative实现MaybeT?

时间:2015-02-14 15:21:48

标签: haskell

重新审视我的{{​​1}}练习后,我发出警告,我应该还有MaybeT个实例。我试图实现它,但因为找不到将Applicative应用于m x m f的方法而陷入困境。我需要Applicative m吗?

Monad m

2 个答案:

答案 0 :(得分:5)

我认为你确实需要Monad。基本上,如果你有

f :: MaybeT m (a -> b)
x :: MaybeT m a

如果在评估f <*> x时,在f中运行展开的m会返回Nothing,那么x的操作就不应该了完全运行 - 但如果不使用mMonad,则无法实现这一点,因为Applicative组合器直观地总是运行所有子行为。

顺便说一句,生成Applicative只是为了满足新AMP要求的最简单方法是使用

import Control.Monad (ap)

instance Applicative ... where
    pure = return
    (<*>) = ap

对于Functor,您可以使用fmap = liftMDeriveFunctor扩展名。

答案 1 :(得分:3)

MaybeT可以定义为

newtype Compose f g x = Composed (f (g x))
newtype MaybeT m x = MaybeT (Compose m Maybe x)

和申请人compose。因此,您可以像这样编写MaybeT的应用实例:

instance Applicative m => Applicative (MaybeT m) where
  pure = MaybeT . pure . Just
  f <*> x = MaybeT $ (<*>) <$> runMaybeT f <*> runMaybeT x

修改

正如@ØrjanJohansen和@dfeuer解释的那样,这不是MaybeT变换器的真实实例,因为(<*>)的定义违反了f <*> x == ap f x定律。这是一个例子:

test :: MaybeT IO ()
test = MaybeT (return Nothing) <*> MaybeT (putStrLn "test" >> return Nothing)

main = runMaybeT test

此代码使用错误的定义打印test,并且不会使用正确的内容打印任何内容。