自己的Monad变压器和起重机

时间:2016-05-11 12:39:33

标签: haskell

data InterpreterM a = ExeInterpreter a | PropInterpreter a

newtype InterpreterMT m a = InterpreterMT { runInterpreterMT :: m (InterpreterM a) }

instance (Monad m) => Monad (InterpreterMT m) where
    return x = lift . return
    x >>= f = InterpreterMT $ do
        m <- runInterpreterMT x
        case m of
            (ExeInterpreter a) -> runInterpreterMT (f a) 

instance MonadTrans InterpreterMT where
    lift m = lift .  (ExeInterpreter m)

我有错误,我不知道为什么:

Interpreter.hs:25:20:
    Couldn't match expected type `InterpreterMT m a'
                with actual type `a2 -> t1 m1 a2'
    In the expression: lift . return
    In an equation for `return': return x = lift . return
    In the instance declaration for `Monad (InterpreterMT m)'

Interpreter.hs:32:18:
    Couldn't match expected type `InterpreterMT m a'
                with actual type `a0 -> t0 m0 a1'
    In the expression: lift . (ExeInterpreter m)
    In an equation for `lift': lift m = lift . (ExeInterpreter m)
    In the instance declaration for `MonadTrans InterpreterMT'

Interpreter.hs:32:27:
    Couldn't match expected type `a0 -> m0 a1'
                with actual type `InterpreterM (m a)'
    In the return type of a call of `ExeInterpreter'
    Probable cause: `ExeInterpreter' is applied to too many arguments
    In the second argument of `(.)', namely `(ExeInterpreter m)'
    In the expression: lift . (ExeInterpreter m)

2 个答案:

答案 0 :(得分:5)

尼古拉斯说。我没有使用无点样式,因此理解类型可能会更容易些。您可以查看示例实现,以便更好地了解变换器 - Control.Monad.Trans.Class

data InterpreterM a = ExeInterpreter a
                    | PropInterpreter a

newtype InterpreterMT m a = InterpreterMT { runInterpreterMT :: m (InterpreterM a) }

instance (Monad m) => Monad (InterpreterMT m) where

--  return :: Monad m => a -> InterpreterMT m a
    return x = InterpreterMT $ (return . ExeInterpreter) x

-- or after you defined MonadTrans below
--  return x = lift . return $ x

--  (>>=) :: Monad m => InterpreterMT m a -> (a -> InterpreterMT m b) -> InterpreterMT m b
    (>>=) ima f = InterpreterMT $ do
        ia <- runInterpreterMT ima
        case ia of
            (ExeInterpreter  a) -> runInterpreterMT $ f a
            (PropInterpreter a) -> runInterpreterMT $ f a

instance MonadTrans InterpreterMT where

--  lift :: Monad m => m a -> InterpreterMT m a
    lift ma = InterpreterMT $ (return . ExeInterpreter) =<< ma

答案 1 :(得分:4)

您似乎在上下文中没有任何MonadTrans实例,因此lift不存在。

但更重要的是,请查看函数的类型。 xa类型的值,return x需要提供(InterpreterMT m) a类型的元素。

为此,您需要使用数据构造函数InterpreterMT并为其指定m (InterpreterM a)

这意味着回归的主体应该像

return . PropInterpreter $ x