2013-05-27 85 views
0

我有以下代码:键访问哈斯克尔

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. 

回答

5

为什么不直接使用现有lookup函数从前奏?

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

此外,您getFirst功能Data.List.find(与以相反的顺序参数)。

+0

哇,与我原来的代码相比,长度减少了70%!感谢提供'find'和'lookup',这真的很有帮助。虽然我很想知道我的原始代码有什么问题。 –

+0

@WilfredHughes:问题在于调用getFirst的结果返回一个带有键和值的Maybe(String,JSValue)。尝试用'fmap snd $ getFirst keyValues keyMatches'替换它以获得'Maybe JSValue'。 – hammar

3

类型的fromJSObject

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

,但在该行

where keyValues = fromJSObject object 

你传递一个JSValue。你只是使用了错误的标识,直接在上面你解构

case object of 
    JSObject a -> 

所以你JSObjecta

where keyValues = fromJSObject a 

应该工作。

另外,getFirstflip find对于findData.List