この記事の問い
Haskellにおいて、「型」や「型の定義」も関数である、と解釈できる?
この記事では、Haskell初心者が地味に嬉しいようなポイントを解説します。
扱うテーマは、上記の問いです。
答えから
Haskellにおいて「型」や「型の定義」そのものを「関数」とみなすことは厳密にはできない。
ただし、ある文脈においては「型は関数のように振る舞う」または「関数と似た性質を持つ」と解釈することは可能。
型定義は「関数定義」とは異なる構文
data Maybe a = Nothing | Just a
これは型 Maybe を定義している。ここでの Maybe は 型コンストラクタ と呼ばれ、型を生成する関数のように振る舞う。
関数的な解釈:
Maybe は型を受け取って型を返す、「型レベルの関数」 のように扱える。
→ つまり「型コンストラクタ = 型レベルの関数」という類推が成り立つ。
ただし「関数」そのものではない:
Maybe は「値」を返す関数ではない。
Maybe は型レベルの存在であり、実行時に評価される値の関数とは別の次元である。
(= 型レベル vs 値レベル)。
型ファミリーやType Functions(より関数的な型)
Haskellでは型レベルの計算を行う「型ファミリー(type families)」という仕組みがあり、これはより明確に「型レベルの関数」である。
type family F a
type instance F Int = Bool
type instance F Bool = Char
ここでは F
は「型を受け取って型を返す関数」そのものとして振る舞っている。
型と関数の「カリー化的性質」
関数と同様に、型コンストラクタも部分適用ができる。この点でも関数と似た性質を持つ。
Either a b -- 通常の2引数型コンストラクタ
Either String -- 1つだけ適用された状態(これは型コンストラクタ `Either String` を得る)
より正確な答え
型、型の定義そのものは関数ではないが、Haskellでは「型コンストラクタ」や「型ファミリー」が関数的に振る舞うため、型を“関数のようなもの”として捉えることができる、というのがより正確な表現となる。
補足 やや専門的な「関数」の定義
Haskellにおける「関数」という概念の定義について、やや専門的な立場からまとめておく。
Haskell における関数とは、型
a -> b
を持つ式であり、入力a
に対して出力b
を対応させる写像である。Haskell の関数はカリー化され、純粋で、first-class citizen
であり、遅延評価・型付きラムダ計算・モナドによる副作用管理といった理論的基盤の上に成り立っている。