次のコードがあるとしましょう
type IsTall = Bool
type IsAlive = Bool
is_short_alive_person is_tall is_alive = (not is_tall) && is_alive
後で、私は次のものを持っているとしましょう
a :: IsAlive
a = False
b :: IsTall
b = True
そして、次のように呼び出して、2 つの引数を間違った方法で取得します。
is_short_alive_person a b
残念ながら、これは正常にコンパイルされ、実行時に、背の低い生きている人の代わりに、背の高い死んだ人が代わりに見つかります。
上記の例をコンパイルしないでください。
私の最初の試みは:
newtype IsAlive = IsAlive Bool
newtype IsTall = IsTall Bool
しかし、私は何かをすることはできません。
switch_height :: IsTall -> IsTall
switch_height h = not h
not
s では定義されていません。sのみIsTall
ですBool
。
Bool
s を常に明示的に抽出することはできますが、それでは目的が大きく損なわれます。
基本的に、明示的なキャストなしではs およびs と相互作用しないことを除いて、 sが s と同じようにIsTall
他の s と相互作用するようにします。IsTall
Bool
Bool
IsAlive
これを達成するための最良の方法は何ですか。
ps GHCで行うことで、数字でこれを達成したと思います:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype UserID = UserID Int deriving (Eq, Ord, Num)
newtype GroupID = GroupID Int deriving (Eq, Ord, Num)
(つまり、UserID と GroupID は相互作用してはなりません)
しかし、私は s でこれを行うことができないようですBool
(Bool の導出は機能しません)。とにかく、上記が最善のアプローチであるかどうかさえわかりません。