如何应用自定义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?