如何摆脱“默认以下约束来输入'[Char]'”警告?

时间:2018-04-10 10:34:46

标签: haskell

我正在使用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 ‘.=’

原因是StringText都是ToJSON的实例,因此编译器必须选择一个,在这种情况下它已选择String

我知道我可以使用内联类型来抑制警告,如下所示:

 toJSON (Foo v) = ["kind" := ("foo" :: Text) ...]

然而,这会使代码与冗余信息混乱。我也收到了很多警告。

我已尝试将default (Text)放在文件的顶部,但这只会更改警告,告诉我默认输入Text

是否有一种方法可以禁用Text / String默认值的警告但是保留其他任何警告?

3 个答案:

答案 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
 (..:) = (.:)