foldの呼び出し順を括弧で表示

(あるいはHaskellの型が邪魔だった事例)

以下のRubyの処理をHaskellでやることを考える

irb> [1,2,3].inject(0){|a,b|[a,b]}
=> [[[0, 1], 2], 3]

まずは素直にリストでやってみる。

Prelude> foldl (\a b->[a,b]) 0 [1,2,3]
    Occurs check: cannot construct the infinite type: a = [a]

当然出来ない。
次にタプルでやってみる。

Prelude> foldl (\a b->(a,b)) 0 [1,2,3]
    Occurs check: cannot construct the infinite type: a = (a, b)

これもだめ。
型を合わせるためにshowで文字列化してみる。

Prelude> foldl (\a b->show (a,b)) "0" [1,2,3]
"(\"(\\\"(\\\\\\\"0\\\\\\\",1)\\\",2)\",3)"

バックスラッシュがえらいことに。
仕方がないので地道に++でつなぐことにする。

Prelude> foldl (\a b->"["++a++","++b++"]") "0" ["1","2","3"]
"[[[0,1],2],3]"

一応出来たけど、Rubyの簡潔さに負けてるのが悔しい。

追記
データ型を定義した場合

data Sexp a = Atom a | List (Sexp a) (Sexp a) deriving Show
main = print $ foldl List (Atom 0) (map Atom [1,2,3])

List (List (List (Atom 0) (Atom 1)) (Atom 2)) (Atom 3)

derivingでついてくるshowの出力だとちょっと見にくい。
あと、入力データ型を変更する(Atomをつける)のが面倒。