Making Illegal States Unrepresentable
具体例
参考
恐らく初出
ぐぐったらいくつかの言語で割と引っかかる

2つのMaybeを必要とする関数で、両方ともJustである必要がある関数の場合は、
2つのMaybeを取るのではなく、 Maybe (a, b)
を取るように修正する
長さの同じ2つのListを取ることを強制するためには、 [(a, b)]
を取るように変えればいい
型の取りうるパターンの数に着目して、隙がないように作ってる
ときには妥協も必要
2つの例で書かれている
emailのverifiedとunverifiedという2つの状態をBooleanで区別するのではなくUnionで書こうな、という話
EmailとAddressのどちらかが必須である、ということを表すために
Maybeとかを使うと、不適切な状態で作られうるので、これもUnionでやろうな、という話
UnvalidateedAddress
と ValidatedAddress
のような型で区別した際に、何かの検査の後に達する状態の方( ValidatedAddress
)はprivateにしておくと良い
たしかに

UnvalidateedAddress
の方は公開していても問題なさそう

オセロの実装で考える
15パターンの時
連絡先には、電子メール、住所、自宅の電話、または勤務先の電話のうち少なくとも 1 つが必要
after.fstype Contact =
{
Name: PersonalName;
PrimaryContactMethod: ContactMethod;
SecondaryContactMethods: ContactMethod list;
}
type ContactMethod =
| Email of EmailContactInfo
| PostalAddress of PostalContactInfo
| HomePhone of PhoneContactInfo
| WorkPhone of PhoneContactInfo
PrimaryContactMethod: ContactMethod
SecondaryContactMethods: ContactMethod list;
とすることで、Primaryの方は必須で、Secondaryの方はoptional(空リスト)とできる
これでもちょっと問題ありそうではある

PrimaryとSecondaryに同じ物が入りうる
Secondary内に重複がありうる
妥協点としては良さそうな気はする
