Haskellでグラフを書くには

Chartとかgnuplotが便利そう。

使い方はそれぞれのサンプルから引用すると、
gnuplotの方は、

plotList [] (take 30 (let fibs = 0 : 1 : zipWith (+) fibs (tail fibs) in fibs))

plotListStyle [] (defaultStyle{plotType = CandleSticks}) (Plot2D.functionToGraph (linearScale 32 (0,2*pi::Double)) (\t -

plotFunc [] (linearScale 1000 (-10,10)) sin
plotFuncs [] (linearScale 1000 (-10,10)) [sin, cos]

plotParamFuncs [] (linearScale 1000 (0,2*pi)) [\t -> (sin (2*t), cos t), \t -> (cos t, sin (2*t))]

let xs = [-2,-1.8..2::Double] in plotMesh3d [] [] (do x <- xs; return (do y <- xs; return (x,y,cos(x*x+y*y))))

Chartの方は、

renderableToWindow (toRenderable $ plotLayout $
                    plot [0,0.1..10] sin "sin(x)") 640 480

plotWindow [0,1,3,4,8] [12,15,1,5,8] "o" "points"

plotPDF "foo.pdf" [0,0.1..10] sin "- " cos ". " cos "o"

plotPS "foo.ps" [0,0.1..10] (sin . exp) "- " (sin . exp) "o-"

と言う感じらしい。

……gnuplotの例の各行の式はそれぞれ型がIO ()で非常にわかりやすいのだけど、Chartの方の型は

Graphics.Rendering.Chart.Simple.PlotWindowType t => t

っていうように、型クラスのインスタンスになっているけど、そのままIO ()を要求される場所(つまりmain)に置けば動いた。そもそも、plotWindowなどは可変長引数をとっているように見えるけど、型が

forall a. PlotWindowType a => a

だし、よく分からない……

実装を見た感じだと、

[a] -> t1 -> IO ()
[a] -> t1 -> t2 -> IO ()
[a] -> t1 -> t2 -> t3 -> IO ()
[a] -> t1 -> t2 -> t3 -> t4 -> IO ()
--以下省略
{-ただし、aはNumのインスタンスで、t1, t2, ...はPlotArgのインスタンス-}

がPlotWindowTypeのインスタンスとなるよう定義されているみたい。