Haskell 14日目 〜 定義と束縛 〜
Haskell 14日目。
本日は定義と束縛に進みます。
定義と束縛
定義と束縛に関わる構文を学びます。
let式
let式を使うと、その式の中でだけ有効な束縛を導入できます。
f n = let x = n + 1 y = n + 2 z = n + 3 in x * y * z
この式の例では変数x,y,zを束縛しています。xの値は「n + 1」で、yの値は「n + 2」、zの値は「n + 3」で、let式を使って束縛した変数はそのlet式内の全体で有効となります。
また、let式の値はinの後に書いた式の値となり、上記の例ならばx * y * zとなります。
let式の構文は以下の通りです。
let 定義1 定義2 定義3 : in 式0
「定義n」は関数束縛かパターン束縛となります。
where節
where節を使うと、特定の定義内でのみ有効な束縛を導入できます。
下記の例では、where節を使って変数baseを1900に束縛しています。
resolveY2K y = base + y where base = 1900
一般にwhere節は次のように書きます。
定義0 where 定義1 定義2 定義3
定義0では、定義1、2、3……を使う事ができます。
「定義n」は関数束縛かパターン束縛です。
定義0が関数の定義であるときは、定義1、2、3……からその関数の引数を参照できます。
下記の例では、where節で導入した関数translateの定義の中から、expandTab関数の引数widthを参照しています。
expandTab :: Int -> String -> String expandTab width cs = concatMap translate cs where translate '\t' = replicate width ' ' tanslate c = [c]
let式とwhere節の違い
let式とwhere節は機能としてはほとんど違わないようにも見えますが、以下の2点で異なります。
- let式は式なのでlet式自体も値を持ちます。しかしwhere節は節なので、値を持ちません。
- where節は複数のガードにまたがって有効です。
where節では以下のような場合でも、(1)、(2)、(3)すべてから関数squareが問題なく参照できます。let式ではこのような事はできません。
foo i | i > 0 = square (i + 1) -- (1) | i == 0 = square 0 -- (2) | i < 0 = square (i - 1) -- (3) where square n = n * n
尚、where節が有効なのは複数のガードであって、複数のパターンではない事に注意が必要です。
以下の例はwhere節ではうまくいかない例です。
bar [] = square 15 -- ここからはsquareが参照できない。 bar (x:xs) = square x where square n = n * n
以上の2点の違いから、それぞれの使われ方に次の傾向があります。
- let式は単純に新しい変数を導入するために使われる。
- where節は関数内で使うための関数を定義するのに使われる。
変数のシャドウイング
関数の引数と同じ名前の変数をlet式で導入すると、そのlet式内ではlet式で導入したyを参照するようになります。
これをシャドウイング(shadowing)と言います。
以下の例ではlet式内でシャドウイングが行われています。
f x y = let y = x * x in y - 1
シャドウイングが起こるのは関数の引数だけでなく、let式がネストした場合、より内側のlet式で導入した変数が外側のlet式の変数を覆い隠します。
定義内での相互参照
let式やwhere節では、同じ構文で導入した束縛を定義の中から参照できます。
次のコードでは変数yの定義のために、同じlet式で束縛した変数xを使っています。
let x = 5 y = x + 2 in x * y
この例では下に書いた定義から上の定義を参照しましたが、逆に上に書いた定義から下の束縛を参照する事もできます。
パターン束縛
Haskellでは関数の仮引数は単なる変数ではなく、値のパターンを記述できました。
それと同じように、let式やwhere節でもパターンを使って変数を束縛できます。
let (x:xs) = [1, 2, 3] in xs
「let (x:xs) = …」という部分がパターンを使った束縛です。これをパターン束縛(pattern bindings)と言います。文字列をパターン(x:xs)で受けて、変数xとxsを束縛しています。結果として1に変数xを束縛し、[2, 3]に変数xsを束縛します。
長かった7章もやっと終わりです。
次から8章 関数に入ります。
今日のところはここまで。
関連記事
[Haskell][プログラミング言語][関数型言語]Haskell 13日目
[Haskell][プログラミング言語][関数型言語]Haskell 12日目
[Haskell][プログラミング言語][関数型言語]Haskell 11日目
[Haskell][プログラミング言語][関数型言語]Haskell 10日目
[Haskell][プログラミング言語][関数型言語]ふつうのHaskellプログラミング
ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門
- 作者: 青木峰郎,山下伸夫
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2006/06/01
- メディア: 単行本
- 購入: 25人 クリック: 314回
- この商品を含むブログ (320件) を見る