2016-12-18 20 views
4

У меня есть этот типа, в основном Клейл стрелок:ApplicativeDo не работает с секвенирование

{-# language DeriveFunctor #-} 

data Plan m i o = Plan (i -> m o) deriving Functor 

instance (Monad m) => Applicative (Plan m i) where 
    pure x = Plan (\_ -> pure x) 
    Plan f <*> Plan x = Plan (\i -> f i <*> x i) 

Поскольку он имеет Applicative экземпляр, я включаю ApplicativeDo и попытаться построить значение, используя делать-обозначения:

{-# language ApplicativeDo #-} 

myplan :: Plan IO()() 
myplan = do 
    pure() 
    pure() 

это не работает:

No instance for (Monad (Plan IO())) arising from a do statement 

есть ли способ сделать это им гк? Я использую GHC 8.0.1.

ответ

0

ApplicativeDo не означает, что do выражений будут всегда быть обессахаренными в терминах аппликативного функтора, но только если это имеет смысл делать это. Здесь нет. Если у вас есть do выражение как

do 
    x <- someAction 
    y <- someAction 
    return (x + y) 

отметить, что порядок на самом деле не имеет значения, так что вы могли бы desugar это

pure (+) <*> someAction <*> someAction 

вместо

someAction >>= (\x -> someAction >>= (\y -> return (x + y)) 

Однако выражение

do 
    pure() 
    pure() 

не имеет никакого выражения, используя только pure и <*>. Это не эквивалентно pure() <*> pure(), потому что первое значение обертывает (), а не функцию. Поскольку нет допустимого способа desugar, используя только экземпляр Applicative, компилятор ищет и не находит экземпляр Monad, чтобы разрешить pure() >> pure().

+7

Это может быть 'pure() *> pure()' хотя. Почему он этого не делает? – Gurkenglas

+2

Я не уверен, есть ли причина, кроме «это не так». Может быть, основная причина, по которой 'a >> b' и' a *> b' может быть тонкой по-другому, или просто может быть, что первоначальная реализация desugaring ограничивает себя 'fmap' и' <*> 'для простоты. – chepner

+4

@chepner Когда я пишу каждое утверждение, подобное '_ <- pure()', похоже, оно работает. – danidiaz