Haskellの関数におけるcase
式の使い方の基本について解説します。
Contents
関数におけるcase式
Haskellは、純粋関数型のプログラミング言語のひとつです。Haskellでのプログラミングでは関数が中心となります。Haskellの関数の基本については「関数の基本」でまとめていますので参考にしてください。
Haskellの関数の実装の際に、条件分岐するために便利な式としてcase
式というものがあります。C/C++等の他の言語を知っている人であればswitch case
のような条件分岐の構文が出てきますが概念としては同じようなものです。
ただし、Haskellのcase
式はそれよりも強力なものです。C/C++のswitch case
では、主に整数値や列挙型との一致で分岐させることに限定されていますが、Haskellのcase
式では値によって評価して分岐するだけではなく、パターンによってマッチさせることも可能であり、より表現力が高くなります。
本記事では、Haskellの関数におけるcase
式の使い方の基本について紹介します。
case
式の基本的な使い方
case
式の構文
case
式の構文は以下のようになります。
case
式
case expression of
pattern1 -> result1
pattern2 -> result2
...
構文自体は非常に分かりやすいかと思います。expression
がpattern1
に該当する場合には、式の評価結果としてはresult1
となります。
case
式の使用例
case
式の簡単な例で使い方を見てみましょう。
data Fruit = Apple | Orange | Banana
fruitColor :: Fruit -> String
fruitColor fruit = case fruit of
Apple -> "Red"
Orange -> "Orange"
Banana -> "Yellow"
【関数使用結果例】
ghci> fruitColor Apple
"Red"
ghci> fruitColor Orange
"Orange"
ghci> fruitColor Banana
"Yellow"
上記例では、Fruit
型という型を定義して、その値としてはApple
, Orange
, Banana
というものを持っています。fruitColor
関数は、Fruit
型の引数を受け取り、その色を返却するような関数です。
case
式では、関数が引数として受け取ったfruit
の値をその後に記載したパターンに合わせて、文字列が変化していることが分かるかと思います。
Haskellのcase
式では、パターンにマッチさせることも可能であることに冒頭で少し触れました。少し複雑な例を見てみましょう。
data Shape = Circle Float | Rectangle Float Float
area s = case s of
(Circle r) -> pi * r * r
(Rectangle w h) -> w * h
【関数使用結果例】
ghci> area (Circle 5)
78.53982
ghci> area (Rectangle 2 5)
10.0
上記例のShepe
型は、 円(Circle
)または矩形(Rectangle
)を表すようなデータ型になっており、どちらであるかで持っている値の数が異なります。case
式のパターンでは、円であれば(Circle r)
、(Rectangle w h)
といったようにパターンによってマッチさせて、値を使った計算式とすることが可能です。
このように、Haskellのcase
式では値の一致やパターンマッチにより条件分岐させることが可能です。
関数の引数に対するパターンマッチとcase
式の違い
Haskellの関数では、引数に対してパターンマッチさせて実装することが可能です。関数の引数に対するパターンマッチについては「関数におけるパターンマッチ」でまとめていますので参考にしてください。
例えば上記で紹介したarea
関数は、関数の引数のパターンマッチとして以下のarea'
関数のように書くことも可能です。
data Shape = Circle Float | Rectangle Float Float
area' :: Shape -> Float
area' (Circle r) = pi * r * r
area' (Rectangle w h) = w * h
関数の引数のパターンマッチとcase
式の違いは、引数に対してパターンを定義するのか、関数内の特定の式に対して行うかという点です。では、どちらを使用するかということになると思いますが、これは解決したい問題によりよく検討する必要があります。
関数のパターンマッチは、引数の型や構造に密接に関連して関数の振る舞いが決まるような場合に特に有用です。汎用的で再利用可能な関数を作成するのに適しています。一方で、case
式は特定の関数内でのみ必要な複雑な条件分岐のロジックを実装する場合に適しています。
最終的にどちらの方法を選択するかは、特定の問題の文脈やコードの可読性、保守性などを十分に考慮して決める必要があります。よりシンプルで直感的な方法を選択できると良いでしょう。
まとめ
Haskellの関数におけるcase
式の使い方の基本について解説しました。
Haskellのcase
式は、C/C++等のswitch case
のような条件分岐に近い概念ですが、より強力なものです。case
式では値によって評価して分岐するだけではなく、パターンによってマッチさせることも可能であり、より表現力が高くなります。
本記事では、case
式の使い方の基本を例を使って紹介しました。また、関数の引数におけるパターンマッチとの違いや使い分けについても説明しています。
case
式は、Haskellの関数定義の表現力を上げるために重要なものになるため、是非使い方を覚えてもらえたらなと思います。