Haskell中任意JSON对象的密钥访问

时间:2013-05-27 22:02:57

标签: haskell

我有以下代码:

import Text.JSON

-- get the value in a JSON object that has this key
getByKey :: JSValue -> String -> Maybe JSValue
getByKey object key =
  case object of
    JSObject a ->
      getFirst keyValues keyMatches
      where keyValues = fromJSObject object
            keyMatches (key', value) = key == key'
    _ -> Nothing

-- get the first item in the list matching a predicate
getFirst :: [a] -> (a -> Bool) -> Maybe a
getFirst [] pred = Nothing
getFirst (x:xs) pred =
  case pred x of
    True -> Just x
    False -> getFirst xs pred

我想用它来访问任意JSValue中的值。但是,它没有编译:

Prelude> :load Example
[1 of 1] Compiling Main             ( Example.hs, interpreted )

Example.hs:8:26:
    Couldn't match expected type `JSValue'
                with actual type `(String, t0)'
    Expected type: JSValue -> Bool
      Actual type: (String, t0) -> Bool
    In the second argument of `getFirst', namely `keyMatches'
    In the expression: getFirst keyValues keyMatches

Example.hs:9:38:
    Couldn't match expected type `JSObject e0'
                with actual type `JSValue'
    In the first argument of `fromJSObject', namely `object'
    In the expression: fromJSObject object
    In an equation for `keyValues': keyValues = fromJSObject object
Failed, modules loaded: none.

我做错了什么?

编辑:Daniel Fischer善意地指出fromJSObject object应为fromJSObject a。但是,这还不足以使类型检查器满意:

[1 of 1] Compiling Main             ( Example.hs, interpreted )

Example.hs:8:16:
    Couldn't match expected type `JSValue'
                with actual type `(String, JSValue)'
    Expected type: [JSValue]
      Actual type: [(String, JSValue)]
    In the first argument of `getFirst', namely `keyValues'
    In the expression: getFirst keyValues keyMatches
Failed, modules loaded: none.

2 个答案:

答案 0 :(得分:5)

为什么不简单地使用Prelude中现有的lookup函数?

getByKey :: JSValue -> String -> Maybe JSValue
getByKey (JSObject obj) key = lookup key (fromJSObject obj)
getByKey _ _ = Nothing

此外,您的getFirst函数为Data.List.find(参数顺序相反)。

答案 1 :(得分:3)

fromJSObject的类型是

fromJSObject :: JSObject e -> [(String, e)]

但在行

where keyValues = fromJSObject object

你传递JSValue。您刚刚在解构的上方使用了错误的标识符

case object of
  JSObject a ->

因此JSObjecta

where keyValues = fromJSObject a

应该有用。

另外,来自getFirst的{​​{3}} flip findData.List