如何应用自定义Monad Transformer

时间:2016-09-09 12:03:12

标签: haskell monads monad-transformers

说我有一些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,然后从中提取一个例子[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 - &gt;例T(IO [a])

我不清楚函数体会是什么样子,以及我最终如何从中提取一个例子[a]?不会runExampleT ExampleT (IO [a])IO [Example a],因此只会在未来的道路上引发多Monad问题吗?

1 个答案:

答案 0 :(得分:2)

你永远无法安全逃脱&#34;来自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