Instance Chains
論文
こういう構文
purs(hs) instance showString :: MyShow String where
myShow s = s
else instance showBoolean :: MyShow Boolean where
myShow true = "true"
myShow false = "false"
instance
宣言に
else
が付いている

型クラスの引数が重複している場合に、どれを選択すれば良いかを明示することができる
型クラスの引数は複数取り得るがまずは1つについて見てみる
purs(hs)class MyShow a where
myShow :: a -> String
instance showString :: MyShow String where
myShow s = s
else instance showBoolean :: MyShow Boolean where
myShow true = "true"
myShow false = "false"
else instance showA :: MyShow a where
myShow _ = "Invalid"
data MysteryItem = MysteryItem
ここでは MyShow
に対してのinstanceを複数個宣言している
instance chainがないと困るのは↓この定義があるせい
purs(hs)instance showA :: MyShow a where
myShow _ = "Invalid"
任意の型 a
に対して、 MyShow
のinstanceを定義している
すると、 MyShow String
を考えたい場合にコンパイラは以下の2つの定義のどちらを採用すべきか自明でなくなる
purs(hs)instance showString :: MyShow String where
myShow s = s
instance showA :: MyShow a where
myShow _ = "Invalid"
これは型エラーになる
MyShow String
は、 MyShow String
でもあるし(当たり前)、 MyShow a
でもある
「上に書いたほうが優先順位が高い」というルールはない
そもそも別ファイルでも定義できる

そこで else instance
を使うことで「上に書いたほうが優先順位が高い」として、これを明示することができる
myShow "hoge"
の場合は、 MyShow String
の定義を採用し、
myShow 100
の場合は、 MyShow a
の定義を採用することになる
purs(hs)class IsEqual (l :: Type) (r :: Type) (b :: Boolean) | l r -> b
instance isEqualRefl :: IsEqual l l True
else instance isEqualDiff :: IsEqual l r False
3引数型クラスのinstanceについて、第1引数と第2引数が同じ型かどうかで定義を分けている
hsにもあるのだろうか?
これ?
参考
purs公式のdocs
説明がうすすぎると思う
3引数型クラスを例に取った説明
簡潔だがdocsよりは詳しい