- Haskellのプログラムはタイプの連なり
- Haskellは、タイプの集合を持ち
- Haskellのプログラムはタイプの連なった構造として表現する。その構造の構成要素(構成タイプ)の数は1以上
- プログラムの中で、タイプの直線的な連なり(紐)となるものは関数と呼ばれる。要素数1のプログラムも関数である。プログラムは関数に分解できる。
- 結局、Hakellのプログラムは、タイプで出来た長さ1以上の紐の連結として作られる。
- Haskellのプログラムが仕事をするとき
- プログラムが仕事をするときには、タイプを実質的なものに変えて考える必要がある
- 個々のタイプ()は、抽象的なもの(具体的でないもの)であり、たとえば、整数である、とか、真偽であるとか、三角形であるとか、そういう概念を表す
- 個々のタイプは、具体的なものを代表しており、具体的な要素を持つ集合であるとも考えられる。たとえば、Intタイプはという具体的な値を持っており、Boolタイプはの2つの具体的な値を持っている。三角形タイプは、その3頂点の座標を決めると形が確定するので、3頂点の座標を使って(Float,Float,Float,Float,Float,Float)という6つの値の組として具体的な要素をとらせることができる。
- このように、タイプがとる具体的な要素は、TrueまたはFalseとか、-Inf,...,-1,0,1,...のいずれか、のように、具体的な要素が列挙された集合となっている場合と、三角形のように、それを指定する引数によって具体性を持たせる場合とがある。
- Haskellでは、これらも、ある意味の関数の実現値とみなす。
- BoolタイプのTrueの場合には、「Trueという関数であって、引数を取らず、TrueというBoolタイプに属する具体的な要素を返す関数」のように考える(コンストラクタである、とも言う。コンストラクタという仕事をする関数でもあり、その実現値でもある)
- 以下のように、TriangleをShapeの1例とし、Triangleの具体的実体を6つの実数値で定めるときには、Triangleはコンストラクタであり、実現値はそれに6引数を与えたときに定まると言う意味で、Triangleは関数である。Quadもコンストラクタであり、8引数を取る関数である
data Shape = Triangle Float Float Float Float Float Float
| Quadrangle Float Float Float Float Float Float Float Float
- クラスというタイプのサブセット
- タイプはたくさんある
- タイプを共通点でサブセットにすることがある
- このサブセットがクラス(またはタイプクラス)である
- 関数とタイプとクラス
- 関数はタイプの連なりと冒頭で書いたが、実際には、タイプクラスの連なりである
- このように定義しておき、単独のタイプを要素数が1のタイプ集合のサブセットとみなせば、すべての関数は1個以上のタイプクラスの連なりである
- こうすることで、1つの関数をいろいろなタイプクラスに使いまわすことができる
- 関数とタイプとその具体的要素実体との関係
- 関数は、タイプ(タイプクラス)の連なりと書いたが、実際は、該当するタイプを受け取る受け皿の連なりである
- 具体的要素実体は、この受け皿にうまく収まる品物である
- したがって、受け皿のつらなりに、うまく納まる品物を収めると、その皿-品物ペアは用がなくなるので、受け皿数が減った状態の関数となる
- ただし、関数の受け皿は埋まる順序が決まっていることに注意する
- タイプの要素実体が引数を取るコンストラクタ関数として定義されているときには、引数にすべての要素実体が収まったときに、そのタイプの要素実体として完成する
- 補遺
- 以下のように定義すると、Hageというのは、何も引数を取らない関数で、Hageという名前のHogeタイプを作るものだとわかる
data Hoge = Hage | Hige
data Hoge = Hage Int Int | Hige Float Float
-
- のように定義できるが、このときHageは関数であって
:type Hage
Int -> Int -> Hoge
:type Hage 3
Int -> Hoge
-
- という型シグナチャになる。それはHageにInt型の具体的な実体3を渡したから、「Intの受け皿」が埋まった」結果だから
- 以下は、Intを取って、その値に関わらずFalseというBool型を返す関数であるが
let f :: Int -> Bool; f x = False
let g :: Int -> Bool; g = f
-
- というように関数gの定義を関数fそのものとすることもできる