模式匹配monad中的值

k_w*_*ski 7 monads haskell monad-transformers

我在haskell中获得了以下数据类型:

data Flow a = Continue a | Return Value
newtype FlowT m a = FlowT {runFlowT :: m (Flow a)}
type IStateM a = FlowT (StateT IState IO) a
Run Code Online (Sandbox Code Playgroud)

其中IState是包含一些列表的记录类型等.FlowT的Monad和MonadTrans实例定义如下:

instance (Monad m) => Monad (FlowT m) where
x >>= f = FlowT $ do
                    unwrapped <- runFlowT x
                    case unwrapped of
                        Continue v -> runFlowT (f v)
                        Return r -> return $ Return r
return x = FlowT $ return (Continue x)


instance MonadTrans FlowT where
    lift m = FlowT (Continue `liftM` m)

instance (MonadIO m) => MonadIO (FlowT m) where
    liftIO m = lift (liftIO m)

instance (MonadState s m) => MonadState s (FlowT m) where
    put k = lift (put k)
    get = lift get
Run Code Online (Sandbox Code Playgroud)

我的意图是,在我正在开发一个解释器的玩具语言中,你可以随时通过调用带有表达式的返回来从函数返回.现在当我编写代码来解释函数的调用时,我需要提取在这个monad中幕后传递的Flow值.我无法与IState()进行模式匹配,因为它包含IO.我需要的函数应该以类似于State的方式工作 - 我调用它并且可以检查是否返回了一些值,如果是,我得到它,如果没有让我们说一些特殊值的Value返回或者某些东西.这该怎么做?

Gab*_*lez 8

要对值进行模式匹配,必须将其结果绑定在给定的monad中,与Monad实例中的方式完全相同:

interpret :: FlowT m a -> m a
interpret flow = do
    value <- runFlowT flow
    case value of
        Continue v -> ...
        Return   r -> ...
Run Code Online (Sandbox Code Playgroud)

作为一个侧面说明,你已经彻底改造的特殊情况,免费单子变压器,你可以找到在正式实施他们free.

具体来说,您的FlowT类型与:

import Control.Monad.Trans.Free  -- from the 'free' package
import Data.Functor.Constant     -- from the 'transformers' package

type FlowT = FreeT (Constant Value)
Run Code Online (Sandbox Code Playgroud)

这给出了一个同构型完全相同的行为,同样MonadMonadTrans实例.

但是回到你的具体问题:不,没有办法在没有首先在基础monad中绑定结果的情况下对值进行模式匹配.