人気ブログランキング | 話題のタグを見る

snoc

Graham Hutton の Programming in Haskell に snoc 関数の説明が出ていた。定義は次のようになる。

Prelude> snoc x xs = xs ++ [x]

これは cons 演算子の逆になる、cons 演算子は次のようにリストの先頭に要素を追加するが、

Prelude> 1:[2,3]
[1,2,3]

snoc 演算子はリストの後ろに要素を追加する。

Prelude> snoc 3 [1,2]
[1,2,3]

何ということはない関数だが、これを foldr の引数にするとリストの逆順を生成する reverse 関数と同じ動作になる。

Prelude> foldr snoc [] [1,2,3,4,5]
[5,4,3,2,1]

魔法みたいだが、foldr を手書きで展開してみるとその意味がわかる。

foldr snoc [] [1,2,3]
= 1 snoc (2 snoc (3 snoc [])))
= 1 snoc (2 sooc ([] ++ [3]))
= 1 snoc (2 snoc [3])
= 1 snoc ([3] ++ [2])
= 1 snoc [3,2]
= [3,2] ++ [1]
= [3,2,1]

直感的には驚くような魔法に感じるが、手作業で関数の結果を展開していくと、その仕組みは納得できる。簡潔すぎるプログラムが驚くような値を返すのが Haskell の魅力だが、自分の手で関数を展開してみると魔法でも何でもないのがわかる。

また、Haskell のプログラムでは重要なのは値の内容ではなく、式の展開という形式であることがわかる。Haskell のプログラムに馴染む一番の方法は手作業で関数を展開して、Haskell のプログラムにおける形式の重要さに気づくことだ。

by tnomura9 | 2018-11-18 09:51 | Haskell | Comments(0)
<< liftM と lift モナドの制御構造 >>