为什么 gnuplot plot 没有从 getContents 接收到完整的标准输入?

Why is gnuplot plot not receiving the entirety of stdin from getContents?

我遇到了惰性 IO 问题,但我不知道如何解决它。
我这里有三个小测试程序,但 V2 才是我真正想要的。
在某处,似乎 getContents 提前停止,或者 gnuplot 提前完成写入。

问题的关键是'how can I take stuff from stdin, and plot it with gnuplot here',但我也想知道如何调试底层问题。

版本 1,不处理 gnuplot。 运行 和 paste <(seq 10000) <(seq 10000) | runhaskell /tmp/hasktest2.hs,按预期打印出 (10000.0,10000.0)。显然所有标准输入都已加载。

import Data.List
main = do
  contents <- getContents
  print . last . map f . lines $ contents

f :: String -> (Double, Double)
f s = (read x, read y)
  where
    [x,y] = words s

V2:正在尝试绘制来自标准输入的任何内容。这是 运行 与 V1 相同的方式 - gnuplot 生成的临时文件被 t运行 处理,所以我没有得到图。但是,如果我 运行 使用 1000 而不是 10k,它确实有效 - 它在编写 gnuplot csv 文件时在某个时候得到 t运行cated,所以我有一行看起来像 1767.0, 1767 没有 \n.

main = do
  contents <- getContents
  plotPathStyle [] (PlotStyle Points (DefaultStyle (1))) . map f . lines $ contents

f :: String -> (Double, Double)
f s = (read x, read y)
  where
    [x,y] = words s

V3:只是为了测试 gnuplot 实际上可以处理 10k 个点,并将它们写入文件 - 这会按预期生成绘图。

import Graphics.Gnuplot.Simple

main = plotPathStyle [] (PlotStyle Points (DefaultStyle (1))) (zip [1..10000] [1..10000] :: [(Double, Double)])

这在很大程度上取决于你最终会得到什么的竞争条件,以及你是否得到一个情节。

函数 plotPathStyle 派生了一个新的 Haskell 线程,其中调用了 gnuplot。该线程使用您传递的列表,因此如果列表是通过惰性 IO 获取的,则只有该线程会实际读取文件。函数 plotPathStyle returns 或多或少立即执行,并且在主线程结束时,程序将关闭。

因此,根据调度的方式,您可能会看到截断的输出或根本看不到 gnuplot window。 (如果我实际编译程序而不是通过 runhaskell 调用,我通常不会得到任何情节。)即使强制使用列表也不能使您免于这种情况。如果您想要非交互式使用(即,不是从 GHCi 内部使用),似乎 gnuplot 包推荐 Graphics.Gnuplot.Advanced 中的界面,它给您更多的控制权,例如允许您明确等待情节完成。