如何应用自定义Monad Transformer

假设我有一些Monadic类型

data Example a = CheckIt {unwrap :: a}

instance Functor Example where
  fmap f (CheckIt x) = CheckIt (f x)

instance Applicative Example where
  pure = CheckIt
  CheckIt f <*> CheckIt x = CheckIt (f x)

instance Monad (Example) where
  return = CheckIt
  e@(CheckIt a) >>= f = f a

我有一个函数返回一个[a]基于一些输入:

fetchList :: b -> [Int]
fetchList _ = [1,2,3,4]

和一个函数返回一个IO [a](从真正的实现简化):

basicIoWrap :: [a] -> IO [a]
basicIoWrap x = return x

我希望运行这个IO然后从中提取一个Example [a]:

以下不起作用:

 foo :: b -> Example [a]
 foo val = (basicIoWrap (fetchList val)) >>= list -> return list

抱怨不同的monad类型

 Couldn't match type ‘IO’ with ‘Example’
      Expected type: Example [a]
        Actual type: IO [Int]

所以我明白这正是Monad变形金刚的用途,但我真的很难找出如何在上下文中应用它们。 假设我有一台变压器:

newtype ExampleT m a = ExampleT {runExampleT :: m (Example a)}

并且我将我的签名改写为foo :: b - > ExampleT(IO [a])

我不清楚函数体将会是什么样子,以及我最终如何从这个提取一个例子[a]? 不会运行runExampleT ExampleT (IO [a])给出一个IO [Example a] ,因此只是在进一步推广多Monad问题?


你永远无法安全地从IO “逃避”,但是如果你有一个像Example (IO [a])这样的类型的值并且Example至少是一个Traversable ,那么你可以把它变成IO (Example [a]) sequence功能。 使用这种方法,你可以写你的foo函数为:

foo :: b -> IO (Example [a])
foo = sequence . return . basicIoWrap . fetchList

由于您必须已经使用IO monad才能使用basicIoWrap ,因此可以访问Example [a] 。 例如:

do input <- getLine
   (Example as) <- foo input
   mapM_ print as
链接地址: http://www.djcxy.com/p/77369.html

上一篇: How to apply a custom Monad Transformer

下一篇: Why are monad transformers different to stacking monads?