Действие IO, вложенное в другие монады, не выполняющиеся
У меня есть
foobar :: IO (ParseResult [(String,String)])
ParseResult - это монада, определенная здесь: https://hackage.haskell.org/package/haskell-src-exts-1.13.5/docs/Language-Haskell-Exts-Parser.html
Я хочу взять эти строки и записать их LaTeXT m ()
определено в https://hackage.haskell.org/package/HaTeX-3.17.1.0/docs/Text-LaTeX-Base-Writer.html
Запуск этой функции не приводит к созданию файла.
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
Создадим новый файл.
Оба набора проверяют тип кода.
1 ответ
Я мог бы получить writeReport2
работает без изменений.
Я думаю, что может быть вашей проблемой является вложенное действие ввода-вывода в возвращаемое значение writeResport2
!
Для того, чтобы сгладить вложенные IO
действия, я должен был использовать функцию join :: Monad m => m (m a) -> m a
от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/stackru-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/stackru-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
если вы хотите, сделайте это, например:
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"