最も単純な型定義として、型略称(エイリアス)があります。

形式は以下の通りです。

type [型名] = [既存の型]

「既存の型」には、すでに見た基本的な型や、これから見ていく拡張された型など、どんな型でも使えます。

例をいくつか挙げてみましょう。

type RealNumber = float
type ComplexNumber = float * float
type ProductCode = string
type CustomerId = int
type AdditionFunction = int->int->int
type ComplexAdditionFunction = 
       ComplexNumber-> ComplexNumber -> ComplexNumber

とても分かりやすいですね。

型略称には二つの利点があります。一つ目は、ドキュメントの役割を果たし、型シグネチャを何度も書く手間を省けることです。上の例では、 ComplexNumberAdditionFunction がその例です。

二つ目は、型の使い方と実際の実装をある程度切り離せることです。上の例では、 ProductCodeCustomerId がこれに該当します。CustomerId を簡単に文字列に変更しても、コードの大部分は変更する必要がありません。

しかし、重要なのは、これはあくまでエイリアスや略称であり、新しい型を作成しているわけではないということです。したがって、明示的に AdditionFunction 型の関数として定義しても、

type AdditionFunction = int->int->int
let f:AdditionFunction = fun a b -> a + b

コンパイラはエイリアスを無視して、単純な int->int->int という関数シグネチャを返します。

特に、本当のカプセル化はできません。 CustomerId の代わりに int をどこでも使用できますし、コンパイラは警告しません。また、次のようにエンティティIDの安全なバージョンを作ろうとしても、

type CustomerId = int
type OrderId = int

期待通りにはいきません。 OrderIdCustomerId の代わりに使ったり、その逆をすることも可能です。本当にカプセル化された型を得るには、後の記事で説明する単一ケースのユニオン型を使う必要があります。

results matching ""

    No results matching ""