Haskell 10日目
Haskell 10日目。
ちょっと間が空きましたが、7章の続きから勉強していきます。
if式
if式の文法
条件判断を行う構文です。if式は次のように書きます。
if 条件式 then 式1 else 式2
条件式はBool型でなければいけません。
式1と式2あいずれも式であって、コードブロックではないことに注意。
if式のコーディングスタイル
if式は次のようなスタイルで書くこともできます。
if c == '\t' then '@' else c
if c == '\t' then '@' else c
パターンマッチ
パターンマッチ(pattern match)とは、値のパターンによる場合分けのことです。
値を調べると同時に、値の一部に変数を束縛することもできます。
パターンマッチを使った定義の例
map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : map f xs
『map f []』と『map f (x:xs)』の部分にパターンマッチが使われています。
『f』はどのような値にでもマッチし、その値に変数fを束縛するパターン
『 []』は空リストにマッチするパターン
『(x:xs)』は空でないリストにマッチして、第1要素を変数xに、第2要素以降のリストを変数xsに束縛するパターンです。
変数パターン(variable pattern)
変数パターンを使った関数定義の例
id :: a -> a id x = x
『_』パターン
『_』パターンを使った関数定義の例
const :: a -> b -> a const x _ = x
『_』パターンは別名ワイルドカード(wildcard)とも言います。
引数『_』が『_』パターンです。
『_』パターンは任意の値にマッチしますが、変数を束縛しません。
関数の引数は必要だが、具体的な値は必要ないという場合に利用します。
リテラルパターン(literal pattern)
リテラルパターンを使った関数定義の例
expandTab :: Char -> Char expandTab '\t' = '@' expandTab c = c
引数の『'\t'』がリテラルパターンです。
リテラルパターンは、値と、指定したリテラルが等しいかどうかを『==』演算子で検査し、等しいときにマッチします。
リテラルパターンに使えるリテラルは、数値リテラル、文字リテラル、文字列リテラルです。
タプルパターン
タプルパターンを使った関数定義の例
format :: (Int, String) -> String format (n, line) = rjust 6 (show n) ++ " " ++ line
『(n, line)』がタプルパターンです。
タプルパターンはタプルにマッチするパターンで、タプルの各要素に対して任意のパターンを記述できます。
リストパターン
リストパターンを使った関数定義の例
last [] = error "last []" last [x] = x last [_:xs] = last xs
『[x]』がリストパターンです。
リストパターンはリストにマッチするパターンで、リストの各要素に対して任意のパターンを記述できます。
データコンストラクタパターン
データコンストラクタの使用例
map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : map f xs
『[]』と『(x:xs)』がデータコンストラクタを使ったパターンです。
『[]』は空リストを作成するデータコンストラクタです。
『:』は新しいリストを作成するデータコンストラクタパターンです。
『@』パターン(as-pattern)
『@』パターンを使った関数定義の例
lstrip str@(c:cs) = if isSpace c then lstrip cs else str
『str@(c:cs) 』で1つの値にマッチするパターンです。
こう書くと、(c:cs)というパターンにマッチさせつつ、その値全体に変数strを束縛させることができます。
ガード
ガードではBool型の任意の式を使って値を検査できます。
ガードを使った関数定義の例
joinPath :: String -> String -> String joinPath a b | null a = pathSep : b | last a == pathSep = a ++ b | otherwise = a ++ pathSepStr ++ b
引数のパターンの後の、『|』(バー)と『=』の間がガードです。
ガードは上から順番に評価され、その値がTrueだったらガードに対応する定義が使われます。
パターンマッチとガード
パターンマッチとガードは、両方あわせて1つの条件です。
つまりガートがすべて失敗した場合は、それに対応するパターンも失敗します。
具体例
f [] = 0 f [x] | x > 0 = 1 f (x:xs) = 2
(f [1])の値は1
なぜなら2番目のパターンにマッチして、そのガードの値もTrueであるため。
(f [-1])の値は2
なぜなら2番目のパターンにマッチしますが、そのガードの値がFalseになるため3番目のパターンにマッチして値が2となります。
今日のところはここまで
関連記事
[Haskell][プログラミング言語][関数型言語]Haskell 9日目
[Haskell][GPGPU][CUDA]なぜGPGPUにHaskellが採用されないのか?
[Haskell]Haskellのリファレンスマニュアルを検索するツール href
[Haskell][プログラミング言語][関数型言語]ふつうのHaskellプログラミング
[プログラミング言語]ハッカーを目指す者が習得すべき5つのプログラミング言語
ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門
- 作者: 青木峰郎,山下伸夫
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2006/06/01
- メディア: 単行本
- 購入: 25人 クリック: 314回
- この商品を含むブログ (320件) を見る