簡體   English   中英

將monadic函數轉換為IO monadic函數

[英]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

我需要在上面返回一個IO (Either ParserError Mod.Module)因為最后的buildModule語句需要執行一些IO功能(讀取文件)。 我遇到的問題是,當我使它成為IO函數時,我不能再進行綁定(錯誤的術語?) <-操作。

使這項工作最簡單的方法是什么?

看一下根據ErrorT ParseError IO定義問題。

我找不到一個組合器來將純Either計算提升到ErrorT monad中,所以我寫了一個名為liftError 我用虛擬類型和實現充實了你的例子。 main運行解析器兩次,一次輸入拋出ParserError ,一次運行IO副作用。 為了使ErrorT ParserError IO成為MonadParserError必須是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM