重新审视我的{{1}}练习后,我发出警告,我应该还有MaybeT
个实例。我试图实现它,但因为找不到将Applicative
应用于m x
m f
的方法而陷入困境。我需要Applicative m
吗?
Monad m
答案 0 :(得分:5)
我认为你确实需要Monad
。基本上,如果你有
f :: MaybeT m (a -> b)
x :: MaybeT m a
如果在评估f <*> x
时,在f
中运行展开的m
会返回Nothing
,那么x
的操作就不应该了完全运行 - 但如果不使用m
是Monad
,则无法实现这一点,因为Applicative
组合器直观地总是运行所有子行为。
顺便说一句,生成Applicative
只是为了满足新AMP要求的最简单方法是使用
import Control.Monad (ap)
instance Applicative ... where
pure = return
(<*>) = ap
对于Functor
,您可以使用fmap = liftM
或DeriveFunctor
扩展名。
答案 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
,并且不会使用正确的内容打印任何内容。