blog1.mammb.com
からの続きです。
条件式
Haskell の if 文は、多くの関数型言語と同じく式です。つまり、なんらかの値を返します。そして else 部がかならず必要です。
整数の絶対値を返却する関数は、条件式を使って以下のように定義できます。
abs :: Int -> Int abs n = if n >= 0 then n else -n
実行結果は以下のようになります。
Main> abs 1 1 Main> abs (-4) 4
条件式はネストすることもできます。例えば以下のように
signum n if n < 0 then -1 else if n == 0 then 0 else 1
ガード
ガードを | にて列挙できます。
abs :: Int -> Int abs n | n >= 0 = n | otherwise = - n
otherwise は常に True を返却するので、最後のガード条件として置いておくと良いです。必須ではないですが。
条件は以下のようにいくつも続けて定義できます。
signum n | n < 0 = -1 | n == 0 = 0 | otherwise = 1
前の例の条件式の定義と比べて非常に読みやすくなっています。
リスト内包表記
リスト内包表記は、以下のように | と <-(数学では∈) により定義します。
lists :: Int -> [Int] lists n = [ x*x | x <- [1..n] ]
x <- [1..n] はジェネレータ部でカンマで区切ることで複数のジェネレータをネストすることもできます。
実行すると以下のようになります。
Main> lists 0 [] Main> lists 4 [1,4,9,16]
ジェネレータをネストすると以下のようになります。
Hugs> [(x, y) | x <- [1, 2, 3], y <- ['a', 'b']] [(1,'a'),(1,'b'),(2,'a'),(2,'b'),(3,'a'),(3,'b')]
リスト内包にはガードを設けることができます。前述の例で、x が偶数の場合のみ結果に含めるようにするには以下のようにします。
lists :: Int -> [Int] lists n = [ x*x | x <- [1..n], x `mod` 2 == 0]
4 を入力として与えると、ガードにより奇数が除外されます。
Main> lists 4 [4,16]
以下のように書いても同じですね。
lists n = [ x*x | x <- [1..n], odd x ]
where節
関数内に where 節で関数を定義できます。where で定義した関数は複数のガードにまたがって可視となります。
psquare :: Num a => a -> a psquare x = (plus x)^2 where plus n = n + 1
psquare 2 とすると (2+1) * (2+1) となり 9 が得られます。
以下のようにして
pmsquare x = (plus x) * (minus x) where plus n = n + 1 minus n = n -1
pmsquare 3 とすると (3+1) * (3-1) となり 8 が得られます。
let式
where 節と似ていますが、こちらは式であり値を持ちます。
上記 where 節と同じ例をlet式で書くと以下のようにできます。
psquare x = let plus n = n + 1 in (plus x)^2
pmsquare x = let plus n = n + 1 minus n = n - 1 in (plus x) * (minus x)
in 以下の結果を式の値として返却します。
where 節で定義した関数のスコープはガードをまたいだのに対し、let式はガードを跨いだスコープは持ちません。
ケース文
case 文は関数定義の本体内でパターンマッチを扱います。
例えばこんな感じです。
tupler xs = case xs of [] -> [] (x:xs) -> [(x,xs)]
あまり意味の無い例ですが、
Main> tupler "hoge" [('h',"oge")]
case 文の中にガードを記載することもできます。
htupler xs = case xs of [] -> [] (x:xs) | x == 'h' -> [('H',xs)] | otherwise -> [(x, xs)]
Main> htupler "hoge" [('H',"oge")]
blog1.mammb.com
につづく