对任意类型实现类型类的坑

1
2
3
4
5
6
7
8
9
10
class DictEnum a where
dictLabel :: a -> Text
dictValues :: [a]
default dictValues :: (Enum a) => [a]
dictValues = enumFrom (toEnum 0)

instance (DictEnum a) => ToJSON a where
toJSON = object [ "label" .= dictLabel val
, "value" .= fromEnum val
]

我想对任意实现了DictEnum的类型自动实现ToJSON,因为他们的json结构是一样的。

如果按照上述方式写,会有问题。因为上述的ToJSON实现针对任意类型,那么没有实现ToJSON的类型会自动使用这个实现,这就导致了不需要实现DictEnum的类型会报错说没有实现DictEnum。

所以,修改了代码改成如下方式

1
2
3
4
5
6
7
8
9
10
class DictEnum a where
dictLabel :: a -> Text
dictValues :: [a]
default dictValues :: (Enum a) => [a]
dictValues = enumFrom (toEnum 0)

defaultDictToJson :: (DictEnum a, Enum a) => a -> J.Value
defaultDictToJson val = object [ "label" .= dictLabel val
, "value" .= fromEnum val
]

在使用的地方实现ToJSON

1
2
instance ToJSON ProficiencyEnum where
toJSON = defaultDictToJson