IO操作嵌套在其他单元未执行 [英] IO action nested in other monads not executing

查看:126
本文介绍了IO操作嵌套在其他单元未执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



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

code>

ParseResult是这里定义的monad: https://hackage.haskell.org/package/haskell-src-exts-1.13。 5 / docs / Language-Haskell-Exts-Parser.html#t:ParseResult



我想把这些字符串写到 rel =nofollow noreferrer> 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
其中
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 \\\
|两个例子如下:\\\
\\\
>>> fib 10 \ 55 \\ n \\ n>>> putStrLn \foo \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\''是一件事:,fib = undefined),(\\\
|这是一件事:\\\
,fibar :: String - > Float)]

itWorks = writeReportAAAA.txt$ docAndGraph testFoo

将创建一个新文件。



两套代码类型检查。

解决方案

我可以在不修改的情况下使用 writeReport2

我认为你的问题可能是嵌套IO动作,它的返回值是 writeResport2



为了使嵌套的 IO 动作变平,我不得不使用功能 join :: Monad m => m(m a) - > Control.Monad

 <$ ma  c $ c> main :: IO()
main = join $ fromParseResult< $> writeReport2test

以下是我的完整代码:

  { - #LANGUAGE OverloadedStrings# - } 

模块Main其中

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示例File \\\
|下面给出了两个示例:\\\
\\\
>>>>>>>>>>>>>< putStrLn \foo \\ ,fib :: Int - > Int

,(\\\
| This is a thing:,fib = undefined)
,(\\\
|这是一件事:\ 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
其中
fileName = name ++.tex
$ b $ main :: IO()
main = join $ fromParseResult< $> writeReport2test

加载到GHCi:

  $ stack ghci 
io-action-nested-in-other-monads-not-executed-0.1.0.0:initial-build-steps(exe)
使用以下软件包配置GHCi:io-action-nested-in-other-monads-not-executed
使用主模块:1.打包'io-action-nested-in-other-monads-not-execution'组件exe:io-action-nested-in-other-monads-not-executable with main-is file:/ home / sven / dev / stackoverflow-questions / io-action-nested-in-other-monads-not-execution /src/Main.hs
GHCi,版本8.0.2:http://www.haskell.org/ghc/:?寻求帮助
从/home/sven/.ghc/ghci.conf加载GHCi配置
编译主(/ home / sven / dev / stackoverflow-questions / io-action-nested- in-other-monads-not-executed / src / Main.hs,解释)
好​​了,加载模块:Main。
从/ tmp / ghci22616 / ghci-script加载的GHCi配置

运行它:

 λ主

创建此文件:

  $ cat test.tex 
\documentclass {article} \begin {document} [(| HaskellExample Example File \\\
|两个例子如下:\\\
\\\
>>> fib 10 \\\
55 \\\
\\\
>>> putStrLn \foo\\\\
bar\\\\
foo\\\
bar,fib :: Int - > Int),(\\\
| This is a thing:,fib =undefined),(\\\
|这是一件事:\ 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 $ b $ z< - execLaTeXT(docAndGraph y)
renderFile fileName z
ParseFailed _ _ - >
return()

main :: IO()
main = writeReport3test


I have a

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

ParseResult is a monad defined here: https://hackage.haskell.org/package/haskell-src-exts-1.13.5/docs/Language-Haskell-Exts-Parser.html#t:ParseResult

I want to take those strings and write them to a LaTeXT m () defined in https://hackage.haskell.org/package/HaTeX-3.17.1.0/docs/Text-LaTeX-Base-Writer.html

Running this function results in no file being created.

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"

However the code:

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

Will create a new file.

Both sets of code type check.

解决方案

I could get writeReport2 working without modification.

I think what might have been your problem is the nested IO action in the return value of writeResport2!

In order to flatten the nested IO actions, I had to use the function join :: Monad m => m (m a) -> m a from Control.Monad:

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

Here is my complete code:

{-# 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"

Loading into 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

And running it:

λ main

Creates this file:

$ 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}%                                                                        

I know it is not the scope of the question, but you could circumvent the nested IO if you want, by doinf this, for example:

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"

这篇关于IO操作嵌套在其他单元未执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆