【问题标题】:How can I test a program reading from stdin in GHCi?如何在 GHCi 中测试从标准输入读取的程序?
【发布时间】:2018-06-19 14:52:44
【问题描述】:

我的程序有一个我想在 GHCi 中查看的错误:

$ ./my-program < ./my-data
Prelude.foldl1: empty list

我尝试在 GHCi 中更改 stdingetLine,但它似乎不会影响我的程序使用的 getLine,即使我之后加载:

$ ghci
Prelude> import System.IO
Prelude System.IO> getLine <- fmap hGetLine $ openFile "my-data" ReadMode
:l "my-program.hs"
:main

我是否需要重写所有 IO 以获取显式句柄才能在 GHCi 中测试它们?

【问题讨论】:

  • 我不是 bash 专家,但我认为您的意思可能是 cat my-data | ./my-program。我认为这应该可行。
  • #UUOC 实际上,cat my-data | ./my-program./my-program &lt; ./my-data 是等价的,但用于生成一个无用的 cat 进程……参见。 Stop Piping Cats
  • 我想知道反对票。关于为什么会有帮助的评论。

标签: haskell testing io interactive ghci


【解决方案1】:

您可以尝试将您的程序包装成这样的内容(经过测试的工作代码):

import qualified System.IO
import qualified GHC.IO.Handle

filename = "/tmp/myfilename"                                                                                                                                                                                                                                                      

main = do                                                                                                                                                                                                                                         
      h <- System.IO.openFile filename System.IO.ReadMode                                                                                                                                                                                         
      old_stdin <- GHC.IO.Handle.hDuplicate System.IO.stdin                                                                                                                                                                                       
      GHC.IO.Handle.hDuplicateTo h System.IO.stdin                                                                                                                                                                                                
      System.IO.hClose h
      realMain
      GHC.IO.Handle.hDuplicateTo old_stdin System.IO.stdin

realMain = ...

也应该可以定义一个用户定义的 GHCi 命令来为任何 GHCi 命令执行此操作,但我还没有尝试过。请参阅 here 以获取使用用户定义的 :redir 命令重定向命令的 stdout 的某人的 .ghci。

【讨论】:

  • hDuplicateTo h System.IO.stdin让我getTerminalAttributes: illegal operation (Inappropriate ioctl for device)
  • @Nowhereman 我刚刚尝试过这个,它在 ghci 中对我有用(修复了代码中的一些错误,所以现在它是一个经过完整测试的 sn-p)。您是否有机会使用 Windows?你实现了 ghci :redir 风格的命令吗?
  • 只有当我将 GHC.Handle 替换为 GHC.IO.Handle 时,您的代码才有效。此外,如果我将它作为文件加载,但如果我在 GHCi 中输入它就不行(我得到同样的错误)。我还没有尝试将它作为命令。
  • 是的,我也在最终版本中替换了 GHC.Handle。
  • 当我在 ghci 中输入类似的定义时,这也对我有用
【解决方案2】:

我想你想要:

ghci> :set args YOUR_ARG
ghci> main

或者

ghci> :main YOUR_ARG

请看这里:How to set a program's command line arguments for GHCi?

【讨论】:

  • 我的程序没有使用任何参数,所以没有。
猜你喜欢
  • 2012-10-31
  • 1970-01-01
  • 1970-01-01
  • 2018-04-28
  • 1970-01-01
  • 2017-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多