我该如何使用json库?

5

我正在尝试弄清楚Haskell的json库。 然而,在ghci中遇到了一些问题:

Prelude> import Text.JSON
Prelude Text.JSON> decode "[1,2,3]"

<interactive>:1:0:
    Ambiguous type variable `a' in the constraint:
      `JSON a' arising from a use of `decode' at <interactive>:1:0-15
    Probable fix: add a type signature that fixes these type variable(s)

我认为这与类型签名中的“a”有关:
decode :: JSON a => String -> Result a

有人能给我展示一下:

  1. 如何解码字符串?
  2. 这里的类型系统是怎么回事?

你应该解码像 ({"key":[1,2,3]}) 这样的字符串,而不是一个纯数组吧? - meder omuraliev
@meder - 没有什么必要,但是一个对象同样可以(应该?)奏效。这只是我选择的一些东西,因为它很容易。 - Jason Baker
3个回答

7

您需要指定要获取的类型,例如:

decode "[1,2,3]" :: Result [Integer]
-- Ok [1,2,3]

如果这一行是一个更大的程序的一部分,你会继续使用 decode 的结果,类型可以被推断出来,但由于 ghci 不知道你需要哪种类型,它无法推断。

这也是为什么没有类型注释或更多上下文的情况下,read "[1,2,3]" 不能工作的原因。


1
唯一的问题是 JSON 是动态类型,这意味着我可能事先不知道类型。 json 库附带了一个 JSValue 类型,您可以使用它:decode "[1,2,3]" :: Result [JSValue] 给出 Ok [JSRational False (1 % 1),JSRational False (2 % 1),JSRational False (3 % 1)]。除此之外,据我所知,这是正确的方法。 - Jason Baker
2
甚至更好的是:decode "[1,2,3]" :: Result JSValue将会返回Ok (JSArray [JSRational False (1 % 1),JSRational False (2 % 1),JSRational False (3 % 1)]) - Jason Baker
2
你已经抓住了问题的关键。Haskell不是动态类型语言,因此如果您想要一种表示未知类型的方法,您需要一些可以捕获所有类型的包装数据类型。JSValue似乎在这里起到了这样的作用。 - Dan

4
解码函数定义如下:
decode :: JSON a => String -> Result a

在一个实际的程序中,类型推断引擎通常可以从decode函数中推断出期望的类型。例如:

userAge :: String -> Int
userAge input = case decode input of
                  Result a -> a
                  _ -> error $ "Couldn't parse " ++ input

在这种情况下,userAge的类型导致类型检查器推断出decode的返回值在这种特定情况下是Result Int
然而,在GHCi中使用decode时,您必须指定该值的类型,例如:
decode "6" :: Result Int
=> Ok 6

2

简单浏览文档似乎表明,该函数的目的是允许您将JSON读入任何支持类型的Haskell数据结构中,因此

decode "[1, 2, 3]" :: Result [Int]

应该能够工作

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接