2017-02-22 53 views
0

我有一個IO動作嵌套在其他單子不執行

foobar :: IO (ParseResult [(String,String)]) 

ParseResult在這裏定義的單子:https://hackage.haskell.org/package/haskell-src-exts-1.13.5/docs/Language-Haskell-Exts-Parser.html#t:ParseResult

我想利用這些字符串,並將其寫入到https://hackage.haskell.org/package/HaTeX-3.17.1.0/docs/Text-LaTeX-Base-Writer.html

定義一個 LaTeXT m()

運行此功能會導致沒有創建文件。

writeReport2 :: [Char] -> IO (ParseResult (IO())) 
writeReport2 name = do x <- foobar 
         return $ do y <- x 
            return $ do z <- (execLaTeXT.docAndGraph) y 
               renderFile fileName z 
    where 
    fileName = name ++ ".tex" 

然而代碼:

writeReport :: t -> LaTeXT IO a -> IO() 
writeReport name report = createLatex >>= renderFile fileName 
    where 
    createLatex = execLaTeXT report 
    fileName = "AAAAA" ++ ".tex" 


testFoo = [(" | HaskellExample Example File\n | Two examples are given below:\n\n >>> fib 10\n 55\n\n >>> putStrLn \"foo\\nbar\"\n foo\n bar ","fib :: Int -> Int"),("\n | This is a thing: ","fib = undefined"),("\n | This is a thing:\n","fibar :: String -> Float")] 

itWorks = writeReport "AAAA.txt" $ docAndGraph testFoo 

將創建一個新的文件。

兩組代碼類型檢查。

回答

3

我可以得到writeReport2沒有修改。

我想可能是你的問題是嵌套IO操作在返回值writeResport2

爲了壓扁嵌套IO行動,我不得不使用功能join :: Monad m => m (m a) -> m a from Control.Monad

main :: IO() 
main = join $ fromParseResult <$> writeReport2 "test" 

這裏是我的完整代碼:

{-# LANGUAGE OverloadedStrings #-} 

module Main where 

import   Language.Haskell.Exts.Parser 
import   Text.LaTeX.Base.Writer 
import   Text.LaTeX 
import   Data.String 
import   Control.Monad 

foobar :: IO (ParseResult [(String, String)]) 
foobar = return (ParseOk testFoo) 

testFoo = [ (" | HaskellExample Example File\n | Two examples are given below:\n\n >>> fib 10\n 55\n\n >>> putStrLn \"foo\\nbar\"\n foo\n bar " 
      , "fib :: Int -> Int" 
      ) 
      , ("\n | This is a thing: ", "fib = undefined") 
      , ("\n | This is a thing:\n", "fibar :: String -> Float") 
      ] 

docAndGraph :: Monad m => [(String, String)] -> LaTeXT m() 
docAndGraph x = do 
    documentclass [] article 
    document $ 
     raw (fromString (show x)) 

writeReport2 :: [Char] -> IO (ParseResult (IO())) 
writeReport2 name = do 
    x <- foobar 
    return $ do 
     y <- x 
     return $ do 
      z <- (execLaTeXT . docAndGraph) y 
      renderFile fileName z 
    where 
    fileName = name ++ ".tex" 

main :: IO() 
main = join $ fromParseResult <$> writeReport2 "test" 

裝入GHCI:

$ stack ghci 
io-action-nested-in-other-monads-not-executing-0.1.0.0: initial-build-steps (exe) 
Configuring GHCi with the following packages: io-action-nested-in-other-monads-not-executing 
Using main module: 1. Package `io-action-nested-in-other-monads-not-executing' component exe:io-action-nested-in-other-monads-not-executing with main-is file: /home/sven/dev/stackoverflow-questions/io-action-nested-in-other-monads-not-executing/src/Main.hs 
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help 
Loaded GHCi configuration from /home/sven/.ghc/ghci.conf 
[1 of 1] Compiling Main    (/home/sven/dev/stackoverflow-questions/io-action-nested-in-other-monads-not-executing/src/Main.hs, interpreted) 
Ok, modules loaded: Main. 
Loaded GHCi configuration from /tmp/ghci22616/ghci-script 

和奔跑摹吧:

λ main 

創建這個文件:

$ cat test.tex 
\documentclass{article}\begin{document}[(" | HaskellExample Example File\n | Two examples are given below:\n\n >>> fib 10\n 55\n\n >>> putStrLn \"foo\\nbar\"\n foo\n bar ","fib :: Int -> Int"),("\n | This is a thing: ","fib = undefined"),("\n | This is a thing:\n","fibar :: String -> Float")]\end{document}%                   

我知道這是不是問題的範圍,但你可以規避嵌套IO如果你想,通過這個doinf,例如:

writeReport3 :: [Char] -> IO() 
writeReport3 name = do 
    let fileName = name ++ ".tex" 
    x <- foobar 
    case x of 
     ParseOk y -> do 
     z <- execLaTeXT (docAndGraph y) 
     renderFile fileName z 
     ParseFailed _ _ -> 
     return() 

main :: IO() 
main = writeReport3 "test" 
+0

您是否恰當地解釋了爲什麼嵌套導致IO操作不能執行? – LambdaScientist

+0

http://stackoverflow.com/questions/42404258/why-will-a-io-nested-in-other-monads-not-execute-is-there-a-way-to-force-them-t/42404828 #42404828 – LambdaScientist