Haskellで名前付き引数やデフォルト引数に近いこと

名前付き引数やデフォルト引数とは

幾つかの言語では、関数の引数に名前を付けて、引数の順番ではなく名前で値を指定することができる。また、引数があたえられなかった時に使用されるデフォルトの値を設定して置くこともできたりする。

func <- function(a, b, c = 1) {
  return(a * b + c)
}

func(b = 3, a = 2)
=> 7

Haskellにはこうした機能はないが、レコード構文を使うと近しいことが実現できる。

Haskellのレコード構文

Haskellではデータ型を定義する時、以下のような記法を用いることで、フィールドに名前を付けることができる。

data MyData = MyData { first :: Int, second :: String, third :: Double }

data1 = MyData 0 "hello" 1.4
data2 = MyData { second = "hello", third = 1.4, first = 0 }

-- アクセサ関数
second data1
=> "hello"

オブジェクトの作成には、data1のような通常の記法に加えて、data2のような記法も利用できる。フィールド名を名前で指定でき、順番はバラバラでも良い。また、フィールド名と同じ名前のアクセサ関数も自動的に用意される。

data3 = data2 { first = 1, second = "world" }

first data3
=> 1

この構文を使うと、オブジェクトの一部のフィールドのみを書き換えた新しいオブジェクトを作成することもできる。

Haskellで名前付き引数とデフォルト引数

関数の引数にレコード構文で定義したデータ型を使うことで、Haskellでも名前付き引数やデフォルト引数に近いことを実現できる。

data Request = Request { repetition :: Int, message :: String }

display :: Request -> IO ()
display (Request n s) = mapM_ (print . (++ " " ++ s) . show) [1..n]

-- 名前付き引数
display Request { message = "record", repetition = 4 }

-- デフォルト引数
req0 = Request { repetition = 3, message = "hello" }
display req0 { message = "world" }