Haskellでグラフ描画

#注意#
今回の内容を実行するにはgtk2hsのインストールが必要です。ボリュームがあるため、ここではgtk2hsのインストールには触れません。既にインストールされている前提とします。

#概要#
Haskellでのグラフ描画の紹介です。今回は[こちらのサイト](https://github.com/timbod7/haskell-chart/wiki)を元にコードを書きました。英語ですが、サンプルがたくさんあります。ただ、GUIで表示するサンプルが見当たらなかったため、ここで紹介しようと思いました。

グラフを描画した画像ファイル(今回はPNG形式)を作成できます。
![quad.png](https://qiita-image-store.s3.amazonaws.com/0/38349/e5cbf02e-6b61-73b5-74fb-efa9c9b0a3d5.png)


グラフをGUIで表示することができます。
![chart-gtk.png](https://qiita-image-store.s3.amazonaws.com/0/38349/ea8e8a21-9bd1-b13f-3c10-af063fc29bbf.png)

#パッケージのインストール#
次のパッケージをインストールします。
##Chart-diagrams##

>cabal update
>cabal install chart-diagrams

##Chart-cairo##

>cabal update
>cabal install chart-cairo

##Chart-gtk##

>cabal update
>cabal install chart-gtk

#コード#
```hs:Main.hs
module Main where

--グラフの定義
import Graphics.Rendering.Chart

--系列の色指定
import Data.Colour
import Data.Colour.Names

--デフォルト値適用
import Data.Default.Class

--グラフ描画(画像ファイル出力)
import Graphics.Rendering.Chart.Backend.Cairo
--グラフ描画(GUI)
import Graphics.Rendering.Chart.Gtk

--「.~」演算子
import Control.Lens

chart :: Renderable ()
chart = toRenderable layout
    where
        --2次関数
        quad :: Double -> Double
        quad = (**2)

        --1つ目の系列
        pl = plot_lines_values .~ [[ (x, (quad x)) | x <- [-50..50]]]
            $ plot_lines_style . line_color .~ opaque blue
            $ plot_lines_style . line_width .~ 3
            $ plot_lines_title .~ "plot_lines"
            $ def

        --2つ目の系列
        pp = plot_points_values .~ [ (x, (quad x)) | x <- [-50,-45..50]]
            $ plot_points_style .~ filledPolygon 5 4 False (opaque magenta)
            $ plot_points_title .~ "plot_points"
            $ def

        --グラフ
        layout = layout_title .~ "y=x^2"
            $ layout_plots .~ [toPlot pl, toPlot pp]
            $ def

main :: IO ()
main = do
    --画像ファイル(PNG形式)出力
    _ <- renderableToFile def "quad.png" chart
    --画面表示
    renderableToWindow chart 640 480

```

#説明#
chart関数でグラフを定義してmain関数でファイル出力、画面表示しています。
今回は2次関数をグラフで描画しました。quad関数がその2次関数です。

```hs
quad :: Double -> Double
quad = (**2)
```

Double型を指定しているのは系列(ここではpl関数(pl :: PlotLines Double Double)、pp関数(pp :: PlotPoints Double Double))の型に合わせています。

layout関数でグラフの設定、pl関数、pp関数で描画するデータ系列の設定を行っています。pl関数は直線、pp関数が点での描画になります。具体的な設定方法をpl関数を例に説明します。

```hs
pl = plot_lines_values .~ [[ (x, (quad x)) | x <- [-50..50]]]
    $ plot_lines_style . line_color .~ opaque blue
    $ plot_lines_style . line_width .~ 3
    $ plot_lines_title .~ "plot_lines"
    $ def
```

plot_lines_valuesやplot_lines_style がプロパティのような感じです。「.~」演算子でプロパティに値を設定、「.」演算子で手前のプロパティの下位プロパティを展開していく感じです。末尾のdef関数により設定していないプロパティには各プロパティの初期値が適用されます。

続いてmain関数の説明です。

```hs
main :: IO ()
main = do
    --画像ファイル(PNG形式)出力
    _ <- renderableToFile def "quad.png" chart
    --画面表示
    renderableToWindow chart 640 480
```

renderableToFile関数でPNG形式画像ファイルを出力しています。他にもSVG、PS、PDF形式が可能なようです(未検証)。renderableToFile関数の戻り値がIO (PickFn ())型だったため、IO ()型に合わせるために「_ <-」で捨てています。
renderableToWindow関数でグラフが描画されたフォームを画面に表示しています。

#実行結果#
概要で紹介したものと同じです。
カレントディレクトリに以下の画像ファイル(PNG形式)が出力されます。
![quad.png](https://qiita-image-store.s3.amazonaws.com/0/38349/e5cbf02e-6b61-73b5-74fb-efa9c9b0a3d5.png)

グラフが描画されたフォームが画面に表示されます。
![chart-gtk.png](https://qiita-image-store.s3.amazonaws.com/0/38349/ea8e8a21-9bd1-b13f-3c10-af063fc29bbf.png)

#補足#
GUI不要の場合はchart-diagramsで実装できればgtk2hsのインストールは不要かもしれません(未検証)。

#参照元#
https://github.com/timbod7/haskell-chart/wiki