我正在使用Aeson库和OverloadedStrings
编译指示,但这个问题更为通用。直接上下文是我正在为sum类型编写代码,所以我在JSON中有一个“kind”字段来说明正在表示哪个变体。在ToJSON实例中,我编写如下代码:
toJSON (Foo v) = ["kind" .= "foo" ...]
toJSON (Bar v) = ["kind" .= "bar" ...]
GHC为"foo"
和"bar"
提供了以下警告:
Defaulting the following constraints to type ‘[Char]’
(ToJSON v0)
arising from a use of ‘.=’
原因是String
和Text
都是ToJSON的实例,因此编译器必须选择一个,在这种情况下它已选择String
。
我知道我可以使用内联类型来抑制警告,如下所示:
toJSON (Foo v) = ["kind" := ("foo" :: Text) ...]
然而,这会使代码与冗余信息混乱。我也收到了很多警告。
我已尝试将default (Text)
放在文件的顶部,但这只会更改警告,告诉我默认输入Text
。
是否有一种方法可以禁用Text / String默认值的警告但是保留其他任何警告?
答案 0 :(得分:3)
为什么不把序列化逻辑的那部分提升到一个单独的函数中?无论如何它都是hacky,所以最好把它分开。并且您将使警告静音(假设您为该功能提供了类型)。
有些事情......
toJSON thing@(Foo v) = ["kind" .= kind thing ...]
toJSON thing@(Bar v) = ["kind" .= kind thing ...]
kind :: T -> Text
kind (Foo _) = "foo"
kind (Bar_) = "bar"
但是你想要这样做。也许使用ViewPattern
或者制作kind :: KeyValue kv => T -> kv
。请不要内联,IMO。
答案 1 :(得分:0)
我想我可能会抽象你正在制作的键值对,如下所示:
kind :: KeyValue kv => Text -> kv
kind lbl = "kind" .= lbl
toJSON (Foo v) = [kind "foo", ...]
toJSON (Bar v) = [kind "bar", ...]
答案 2 :(得分:0)
最后,我从评论中提出了Thomas DuBuisson的建议,并添加了几个专门的功能:
-- | Type-restricted version of "(.=)" to silence compiler warnings about defaults.
(..=) :: (KeyValue kv) => Text -> Text -> kv
(..=) = (.=)
-- | Type restricted version of "(.:)" to silence compiler warnings about defaults.
(..:) :: Object -> Text -> Parser Text
(..:) = (.:)