TL;DR
- 単純型にも、桁数や範囲のような制約がある。
- コンストラクタをプライベートにし、無効な値ならエラーを返す関数を用意して、不正な値を作れないようにする(スマートコンストラクタ)。
内容
単純型の制約
単純型にも制約はある。次の例では、制約をコメントで書いている。
type WidgetCode = WidgetCode of string // 先頭が "W" + 数字 4 桁
type UnitQuantity = UnitQuantity of int // 1 以上 1000 以下
type KilogramQuantity = KilogramQuantity of float // 0.05 以上 100.00 以下しかし本当は、制約を満たさない値をそもそも作れないようにしたい。
スマートコンストラクタ
F# では、コンストラクタをプライベートにして別の関数を用意し、無効な値ならエラーを返すようにする。この方法をスマートコンストラクタと呼ぶ。エラーは Result で返す。
module UnitQuantity =
type UnitQuantity = private UnitQuantity of int
let create qty =
if qty < 1 then
Error "UnitQuantity can not be negative"
else if qty > 1000 then
Error "UnitQuantity can not be more than 1000"
else
Ok (UnitQuantity qty)
// ラップされたデータを取り出す関数
let value (UnitQuantity qty) = qty使うときは次のようになる。
let unitQtyResult = UnitQuantity.create 1
match unitQtyResult with
| Error msg -> printfn "Failure, Message is %s" msg
| Ok uQty ->
printfn "Success. Value is %A" uQty
let innerValue = UnitQuantity.value uQty
printfn "innerValue is %i" innerValueキーワード
自分の理解
スマートコンストラクタは、F# 以外の言語でも再現できる。Dart での例は naoty さんの記事を参照。