1.概略
「パターン照合」の記事で、ガードによる場合分けを説明した。しかし、関数の入り口ではなく、式の途中の中で場合分けをしたいときがある。例えば、無名関数の中でというときがそうである。
このような時利用されるのが、if式またはcase式である。
if式はは次のようになる。
if expression then true-value else false-valu
if expression then true-value else false-valuとなる。ここで、expressionは条件式、true-valueは真の時に返す値、false-valuは偽の時に返す値である。
case式は次のようになる。case式では、パターン照合も使うことができる。その例は、例題の中の問題で示す。
case expression of pattern -> result pattern -> result pattern -> result .........
2.例題
問題:関数lengthListは入力されたリストの長さが20以上の時longと返し、10から19までの時はmiddleを返し、10未満の時はshortを返す。if式を用いてlengthListを実現しなさい。
解答
プログラムは次のようになる。
lengthList :: (Eq a) => [a] -> String lengthList lst = if length lst >= 20 then "long" else if length lst >= 10 then "middle" else "short"
また、実行結果は次のようになる。
*Main> lengthList "asd" "short" *Main> lengthList "asdweiktgpjeokertnskfed" "long" *Main> lengthList "asdweiktgpje" "middle"
問題:空のリスト、一要素のリスト、複数要素のリストを場合分けする関数listKindを作成しなさい。
解答
プログラムは次のようになる。
listKind :: (Eq a) => [a] -> String listKind lst = case lst of [] -> "Empty" [_] -> "Singleton" _:_ -> "List"
実行結果は次のようになる。空のリストはEmpty、一要素のリストはSingleton、複数要素のリストはListと出力される。
*Main> listKind "a" "Singleton" *Main> listKind "" "Empty" *Main> listKind "asd" "List" *Main> listKind [1,2,3] "List" *Main> listKind [1] "Singleton"
3.問題
それでは問題を解いてみる。
問題1:例題の最初の問題lengthListを、ガード | を用いて表せ。
問題2:例題の二番目の問題lengthListを、caseを用いずにパターン照合だけで表しなさい(即ち、listKindの引数をそれぞれのパターンで表す)。
問題3:ifを用いて、入力された値が100以上の時はlargeと、10以上の時はmiddleと、それ以外の時はsmallと出力する関数を作成しなさい。
問題4:問題3を、ガード | を用いて表せ。
問題5:caseを用いて、次の関数を作成しなさい。関数への入力は対である。対の左側の要素を数字であり、右側の要素は文字である。数字が0であるときFalseを、それ以外の時Trueを出力する。
問題6:問題5をcaseを用いずにパターン照合だけで表しなさい。
問題7:問題5をifを用いて作成しなさい。
問題8:関数zipと無名関数を用いて次の関数を実現しなさい。この関数は、二つの数列を入力した時、次のように、真理値を対とするリストを出力する。両方の数列とも、それぞれの要素が、奇数であればFalseに、偶数であればTrueに変更する。例えば、入力が、[1,3..]と[2,4..]の時は、[(False, True),(False, True),(False, True),...]が出力される。
問題9:問題8において、数が100以上の時はlargeと、10以上の時はmiddleと、それ以外の時はsmallに変更するようにしなさい。
問題10:問題8において、caseを用いて、苗字と名前のリストを入力したとき時、イニシャルのリストを出力しなさい。例えば、["Tanaka", "Sato",..]が苗字のリストで、["Hanako", "Taro",..]が名前のリストである時、["HT","TS"..]を出力する。