一次リスト

以下をfoo.lhsとし hugs foo.lhsで実行可能。

haskellではリストは a:b:c:[] で表され、その省略形は[a,b,c]となる。
リストの全ての要素を足しあわせる関数sumlistを定義する

>sumlist [] = 0
>sumlist (x:xs) =  (+) x (sumlist xs)

次にリストの全ての要素を掛け合わせる関数multilistを定義する

>multilist [] = 1
>multilist (x:xs) = (*) x (multilist xs)

実行結果はそれぞれ以下のようになり正しいことが分かる
Main> sumlist [1,2,3]
6
Main> multilist [2,3,4,5]
120
ここで、sumlistとmultilistは演算子と[]のときの動作のみが異なるので高階関数reduceを以下のように定義すると

>reduce f x []= x
>reduce f x (y:ys) = f y (reduce f x ys) 

sumlist,multilistは以下のように定義される。

>sumlist2 = reduce (+) 0
>multilist2 = reduce (*) 1

このreduceについて考察してみる

二つのリストを接続する関数appendは以下のように定義される

>append [] b = b
>append (x:xs) b = (:) x (append xs b)

やはりappendもリストに対する繰り返しであることが分かるので、演算子を(:) []時の値bを引数としてreduceに与えてやればいい。

>append2 a b = reduce (:) b a

とりあえず実行結果

Main> append2 ["a","b","c"] ["d","e"]
["a","b","c","d","e"]
Main> append2 [3,4,5,7][1,2]
[3,4,5,7,1,2]

リストの各要素の値を倍にするdoublelistという関数を考える。

>doublelist [] =  []
>doublelist (x:xs) = (:) ((*) 2 x) (doublelist xs)

doubleandconsを以下のように定義し

>doubleandcons_pre a b = (:) ((*) 2 a) b

ここでbは省略可能なので(理由がうまく説明できない)、reduceでdoublelistを定義し直す

>doubleandcons a = (:) ((*) 2 a)
>doublelist2 = reduce doubleandcons [] 

doubleandconsの演算子をパラメータにすることが出来るから

>fandcons f x = (:) (f x)
>double x = (*) 2 x
>doublelist3 = reduce (fandcons double) []

ここでdoubleを引数とする関数をmap(標準にある関数なのでmap2とする)として定義する

>map2 f = reduce (fandcons f) []
>doublelist4 = map2 double

このmap2を利用する
各要素の値に+1するplusonelistが簡単にかける
各要素の値に/2するhalflistが簡単にかける
(*2)は二倍する関数 例:(*2) 2 --> 4

>plusonelist = map2 (+1)
>halflist = map2 (/2)