为什么gnuplot plot没有从getContents接收到整个stdin



我有一个懒惰IO的问题,但我不知道如何解决。
我这里有三个小的测试程序,但V2是我真正想要的
在某个地方,似乎要么getContents提前停止,要么gnuplot提前完成了编写。

问题的关键是"我如何从stdin中获取内容,并在这里使用gnuplot进行绘图",但我也想知道如何调试底层问题。

版本1,没有处理gnuplot。使用paste <(seq 10000) <(seq 10000) | runhaskell /tmp/hasktest2.hs运行,按预期打印出(10000.0,10000.0)。显然,所有stdin都已加载。

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:试图绘制来自stdin的内容。这是以与V1相同的方式运行的——gnuplot生成的临时文件被截断,所以我没有得到绘图。然而,如果我使用1000而不是10k运行,它确实有效——在编写gnuplot csv文件时,它会在某个时候被截断,所以我有一行看起来像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或多或少会立即返回,在主线程结束时,程序将关闭。

因此,根据调度的方式,您可能会看到被截断的输出或根本没有gnuplot窗口。(如果我真的编译了程序,而不是通过runhaskell调用,我通常不会得到任何绘图。)即使强制列表也不会让你摆脱这种情况。如果您想要非交互式使用(即不在GHCi中使用),gnuplot软件包似乎建议使用Graphics.Gnuplot.Advanced中的接口,这会给您更多的控制权,例如允许您明确等待绘图完成。

最新更新