[英]Converting a monadic function to an IO monadic function
parseSource :: String -> Either ParserError Mod.Module
parseSource src = do
(imports, rest) <- parseImports (Lex.lexSource src)
bindings <- mapM parseBinding rest
buildModule imports bindings
I need to make the above return an IO (Either ParserError Mod.Module)
as the buildModule
statement at the end will need to perform some IO functions (reading files). 我需要在上面返回一个IO (Either ParserError Mod.Module)
因为最后的buildModule
语句需要执行一些IO功能(读取文件)。 The problem i have is that when i make it an IO function, i can no longer do the bind(wrong term?) <-
operations. 我遇到的问题是,当我使它成为IO函数时,我不能再进行绑定(错误的术语?) <-
操作。
What is the simplest way to make this work? 使这项工作最简单的方法是什么?
看一下根据ErrorT ParseError IO定义问题。
I couldn't find a combinator to lift a pure Either
computation into the ErrorT
monad, so I wrote one called liftError
. 我找不到一个组合器来将纯Either
计算提升到ErrorT
monad中,所以我写了一个名为liftError
。 I fleshed out your example with dummy types and implementations. 我用虚拟类型和实现充实了你的例子。 The main
runs the parser twice, once with input that throws a ParserError
, and once which succeeds with an IO
side-effect. main
运行解析器两次,一次输入抛出ParserError
,一次运行IO
副作用。 In order for ErrorT ParserError IO
to be a Monad
, ParserError
must be an instance of Error
(so that it is possible to implement fail
). 为了使ErrorT ParserError IO
成为Monad
, ParserError
必须是Error
一个实例(这样才有可能实现fail
)。
import Control.Monad.Error
type ParserMonad = ErrorT ParserError IO
data ParserError = ParserError1 | ParserError2 | ParserError3
deriving(Show)
data Module = Module
deriving(Show)
data Import = Import
deriving(Show)
data Binding = Binding
deriving(Show)
instance Error ParserError where
noMsg = undefined
-- lift a pure Either into the ErrorT monad
liftError :: Monad m => Either e a -> ErrorT e m a
liftError = ErrorT . return
parseSource :: String -> ParserMonad Module
parseSource src = do
(imports, rest) <- liftError $ parseImports (lexSource src)
bindings <- liftError $ mapM parseBinding rest
buildModule imports bindings
lexSource :: String -> [String]
lexSource = return
parseImports :: [String] -> Either ParserError ([Import], [String])
parseImports toks = do{ when (null toks) $ throwError ParserError1
; return ([Import], toks)
}
parseBinding :: String -> Either ParserError Binding
parseBinding b = do{ when (b == "hello") $ throwError ParserError2
; return Binding
}
buildModule :: [Import] -> [Binding] -> ParserMonad Module
buildModule i b = do{ liftIO $ print "hello"
; when (null b) $ throwError ParserError3
; return Module
}
main = mapM (runErrorT . parseSource) ["hello", "world"]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.