TL;DR
- 合成可能な型システムは、型を組み合わせるだけで複雑なモデルを作れるので、ドメイン駆動設計の大きな助けになる。
- 型には振る舞いがないので、代わりに関数を表す型を定義する。
内容
型を組み合わせてモデルを作る
E コマースサイトで支払いを追跡する例で、型を組み合わせてドメインモデルを作る流れを見る。
まず、小切手番号のようなプリミティブ型のラッパーを単純型として定義する。
type CheckNumber = CheckNumber of int
type CardNumber = CardNumber of string次に、単純な AND 型や OR 型で低レベルの型を作る。カードの種類、カードの情報、支払い方法がこれにあたる。
type CardType = Visa | Mastercard
type CreditCardInfo = {
CardType : CardType
CardNumber : CardNumber
}
type PaymentMethod =
| Cash // 現金
| Check of CheckNumber // 小切手
| Card of CreditCardInfo // カード支払い金額や通貨のような基本的な型も定義する。
type PaymentAmount = PaymentAmount of float
type Currency = EUR | USD最後に、これらを組み合わせてトップレベルの型である支払いを作る。
type Payment = {
Amount : PaymentAmount
Currency : Currency
Method : PaymentMethod
}振る舞いは関数の型で表す
ここまでの型はただの型なので、振る舞いを持たない。振る舞いは、関数を表す型として定義する。たとえば、Payment を使って未払いの請求書を処理し、支払い済みの請求書を返す処理は次のように書ける。
type PayInvoice =
UnpaidInvoice -> Payment -> PaidInvoice支払いをある通貨から別の通貨に変換する処理は次のようになる。
type ConvertPaymentCurrency =
Payment -> Currency -> Payment