✏️

[Haskell]:条件分岐

に公開

🔷 if式

if-then-elseで条件分岐を行うことができる。

🔸 特徴

  • ▫️ 他のプログラミング言語のようにelseを省略することはできない。
  • ▫️ 入れ子構造(else ifに似た形)にすることで、複数の条件分岐を行うことができる。

🔸 例

describeNumber:: Int -> String
describeNumber x = 
    if x < 0 
        then "負の数"
    else if x == 0
        then "ゼロ"
    else if x `mod` 2 == 0
        then "正の偶数"
    else 
        "正の奇数"

以下のように他の言語のようにelseを省略することはできない。

main :: IO()
main = do
  let x = 10
  if x `mod` 2 == 0
     then print "偶数"
     -- エラー:elseを省略することはできない。

🔷 case式

他のプログラミング言語のswitch文に似たような機能を持つ。
値を指定したパターンを比較して、マッチしたパターンに応じた処理をするパターンマッチングを行うことができる。

🔸 特徴

  • ▫️ 式として値を返すことができる。
  • ▫️ ワイルドカードのパターンとして_を使用できる。(switch文のdefaultに相当)
  • ▫️ ガード構文を使用することで条件付きマッチングを行うことができる。

🔸 例 : 基本的なcase式

describeDirection :: String -> String
describeDirection dir = case dir of
  "北" -> "北を向いています"
  "南" -> "南を向いています"
  "東" -> "東を向いています"
  "西" -> "西を向いています"
  _ -> "有効な方角ではありません" 

🔸 例 : ガードを使ったcase式

describeDigitCount :: Int -> String
describeDigitCount n = case n of
  n | n < 0     -> "負"
    | n < 10    -> "1桁"
    | n < 100   -> "2桁"
    | n < 1000  -> "3桁"
    | n < 10000 -> "4桁"
    | otherwise -> "5桁以上"

🔷 パターンマッチング

関数定義を複数のパターンで記述することにより、引数の値に応じて処理を分岐させることができる。

🔸 特徴

  • ▫️ 引数に変数名(例:x)を指定した場合、 任意の値にマッチし、その値を関数内で使用することができる。
  • ▫️ 引数に固定値(例:1)を指定した場合、その値のみにマッチする。
  • ▫️ 引数にワイルドカード(_)を指定した場合、任意の値にマッチするが、値を関数内で使用することができない。
  • ▫️ 上から順に評価され、最初にマッチしたパターンで処理が実行される。

🔸 例

describeDirection :: String -> String
describeDirection "北" = "北を向いています"
describeDirection "南" = "南を向いています"
describeDirection "東" = "東を向いています"
describeDirection "西" = "西を向いています"
describeDirection direction = "「" ++ direction ++ "」は有効な方角ではありません"
-- ワイルドカードの場合は、関数内で値は使えない。
-- describeDirection _ =  "有効な方角ではありません" 

🔷 ガード

複数の条件判定を優先度順に定義して、処理を分岐させることができる。

🔸 特徴

  • ▫️ 複数の条件を定義して、処理を分岐できる。
  • ▫️ otherwiseによって、任意の条件にマッチする。
  • ▫️ 上から順番に条件が評価されて、最初にマッチした条件で処理が行われる。
  • ▫️ パターンマッチングと一緒に使用することができる。

🔸 例 : 基本的なガード

describeDigitCount :: Int -> String
describeDigitCount n
    | n < 0     = "負"
    | n < 10    = "1桁"
    | n < 100   = "2桁"
    | n < 1000  = "3桁"
    | n < 10000 = "4桁"
    | otherwise = "5桁以上"

🔸 例 : パターンマッチングとの組み合わせ

describeDigitCount :: Int -> String
describeDigitCount n | n < 0     = show n ++ "は負の数です"
describeDigitCount n | n < 10    = show n ++ "は1桁です"
describeDigitCount n | n < 100   = show n ++ "は2桁です"
describeDigitCount n | n < 1000  = show n ++ "は3桁です"
describeDigitCount n | n < 10000 = show n ++ "は4桁です"
describeDigitCount n = show n ++ "は5桁以上です"
-- または
describeDigitCount :: Int -> String
describeDigitCount n
    | n < 0     = show n ++ "は負の数です"
    | n < 10    = show n ++ "は1桁です"
    | n < 100   = show n ++ "は2桁です"
    | n < 1000  = show n ++ "は3桁です"
    | n < 10000 = show n ++ "は4桁です"
    | otherwise = show n ++ "は5桁以上です"

🔷 参考

https://zenn.dev/masahiro_toba/articles/39aa954f402e27
https://qiita.com/rooooomania/items/1623e5b981a30fbc8427

Discussion