TL;DR
- 省略可能な値は Option、失敗しうる処理は Result という選択型で表す。
- 値がないことは
unitで表し、ドメインモデルのコレクションにはlistを使う。
内容
省略可能な値
省略可能な値は、Option という選択型(判別共用体)で表す。Some はデータがあることを、None はデータがないことを表す。
type Option<'a> =
| Some of 'a
| Noneドメインモデルでは、次のように使う。Option<string> は string option とも書ける。
type PersonalName = {
MiddleInitial : Option<string>
// ...
}
type PersonalName = {
MiddleInitial : string option
// ...
}エラー
エラーは、Result という選択型で表す。例外を使う方法もあるが、Result を使うと「失敗する可能性がある」という事実を型シグネチャで明示できる。Ok には成功したときの値を、Error には失敗したときのエラーデータを入れる(F# のドキュメント)。
type Result<'T,'TError> =
| Ok of ResultValue:'T
| Error of ErrorValue:'TErrorたとえば、請求書の支払いが失敗する可能性があるなら、次のように書く。エラーの型には、起こりうるエラーのケースを並べた選択型を使う。
type PayInvoice =
UnpaidInvoice -> Payment -> Result<PaidInvoice, PaymentError>
type PaymentError =
| CardTypeNotRecognized
| PaymentRejected
| PaymentProviderOffline値が存在しないこと
関数型プログラミングでは、すべての関数が何かを返さなければならないので、void は使えない。代わりに、() という値だけを持つ unit 型を使う。乱数の生成やデータベースの操作など、副作用を扱うときに使う。
type NextRandom = unit -> int
type SaveCustomer = Customer -> unitリストとコレクション
F# には次のコレクションがある。
list: 固定サイズのイミュータブルなコレクション(連結リスト)array: 固定サイズのミュータブルなコレクション。インデックスで要素を取得・代入できるResizeArray: 可変サイズの配列。要素を追加・削除できるseq: 遅延評価のコレクション。要素は必要になったときに返される
ドメインモデリングでは list を使うことが推奨されている。
type Order = {
OrderId : OrderId
Lines : OrderLine list
}リストはリストリテラルで作り、:: 演算子(cons)で先頭に要素を足せる。
let aList = [1; 2; 3]
let aNewList = 0 :: aList要素を取り出すときは、パターンマッチを使う。
let printList1 aList =
match aList with
| [] -> printfn "list is empty"
| [x] -> printfn "list has one element: %A" x
| [x;y] -> printfn "list has two elements: %A and %A" x y
| longerList -> printfn "list has more than two elements"
let printList2 aList =
match aList with
| [] -> printfn "list is empty"
| first::rest ->
printfn "list is non-empty with the first element being: %A" firstキーワード
自分の理解
F# では、Option<string> よりも string option の書き方のほうが好まれている気がする。