⛑️

Haskellで比較/判定を行う4つの方法(if/case/パターンマッチ/ガード)

2022/05/16に公開
2

この記事ではHaskellで比較/分岐を行う4つの方法をまとめています。基本的な構文を整理したいと思います。

1、if式

私たちが最も慣れ親しんだifを使った判定です。Haskellのifは文ではなく式である点に注意して下さい。文は命令ですが、式は必ず値を持ちます。Haskellのif式では失敗した場合に返却する値も必ず指定しなくてはいけません。 数値が10以上かどうか?をここでは判定しています。

keisan :: Int -> String
keisan x =
    if x > 10
        then "10より大きいです"
        else "10未満です"

main = putStrLn $ keisan 20

keisan関数の中でif式を使って判定を行なっています。「そうでない場合」をelseによって指定しています。またif elseの連鎖をつなげることもできます。

hantei :: Int -> String 
hantei x =
    if x > 10
        then "10より大きいです"
    else if x < 10
        then "10より小さいです"
    else
        "10と同じです"

main = putStrLn(hantei 15)

2、case式

対応する整数によって判定する方法です。 引数として渡された数値によって判定を行います。ここでは生徒の番号によって名前を返却します。どれにも当てはまらない場合にはワイルドカード_の値が返却されます。

getNum num =
    case num of
        1 -> "ハリー"
        2 -> "ロン"
        3 -> "ハーマイオニー"
        _ -> "1~3で入力して下さい"
main = putStrLn $ getNum 2

=ではなく->を使っている点に注意して下さい。命令型言語のswitch caseに似た使い方となっています。

3、パターンマッチ

引数の値による条件分岐です。 引数の値が10であるか?をここでは調べます。

hantei :: Int -> String
hantei 10 = "10です"
hantei x = "10ではありません、" ++ show x ++ "です"

main = putStrLn $ hantei 20
-- 実行結果「10ではありません、20です」

hantei xによって何にでも合致するパターンとなります。引数はxに束縛されるので、xを使って最後は文章を出力してみました。同じことがワイルドカード_を使ってもできます。ワイルドカード_を使うと全ての引数で一致するようになります。

hantei :: Int -> String
hantei 10 = "10です"
hantei _ = "10ではありません"

main = putStrLn $ hantei 20

ただしワイルドカードを使った場合、関数に渡した数値を引数として利用できません。変数に束縛するパターン、ワイルドカードを使うパターンで上手く使い分けて下さい。

4、ガード

引数の性質によって場合分けする仕組みです。 具体的な値を指定する必要がなく、条件による判定ができます。上から順に判定を行なっていき、今回はotherwiseによってどれにも当てはまらなかった場合に返却する式を指定しています。

hantei :: Int -> String
hantei x
  | x > 10 = "10より大きいです"
  | x < 10 = "10より小さいです"
  | otherwise = "10と同じです"

main = putStrLn(hantei 15)

関数名の後ろに=は不要です。ガードを使えばif elseを長々と続けるよりもスッキリと記述できますよね。2つの引数を受け取って大きい方を返却する関数..というのもスッキリと実装できます。

max' :: (Ord a) => a -> a -> a
max' num1 num2
    | num1 <= num2 = num2
    | otherwise  = num1
    
main = print $ max' 10 20
-- 実行結果「20」

Discussion

YAMAMOTO YujiYAMAMOTO Yuji
  • 「比較」と言うより「分岐」といった方が適当かと思います。「比較」するだけなら x == 1 の式だけでも比較ですし
  • 「パターンマッチ」や「case式」の節で数値によるパターンマッチしか行っていないのは何か意図があるんですか?
鳥羽眞嘉鳥羽眞嘉

コメントを下さりありがとうございます。確かにおっしゃる通りです、比較というよりか分岐が正しい表現だと思います。記事の方も修正しておきます。数値によるパターンマッチしか紹介してないのは単純に例として理解しやすいからです。少し内容が物足りないですよね、すみません..