6

私はレンズの魔法に非常に慣れていないので、これに問題があります。

参照: https://www.fpcomplete.com/user/tel/lens-aeson-traversals-prisms

JSON オブジェクトは、次の方法でトラバースできます。

val ^? nth 0 . key "someObject" . key "version" . nth 2

次のような JSON オブジェクトの場合:

"[{\"someObject\": {\"version\": [1, 0, 3]}}]"

Maybe モナドは全体で使用されているため、「アクセサ」が失敗すると、Nothing.

どのアクセサーが失敗したかがわかるように、失敗も伝播したいと思います。

私が考えることができる唯一の方法は、アクセサーの配列を渡し、それらを順番に適用し、失敗した時点でエラーを返すことです。このようなもの:

import Data.Aeson
import Data.Text
import Data.Vector ((!?))
import qualified Data.HashMap.Strict  as HM

data MyAccessor = Nth Int | Key Text 

withFailure :: Value -> [MyAccessor] -> Either String Value
withFailure val [] =  Right val 
withFailure val (x:xs) = case x of
    Nth i -> case val of        
        (Array val') -> case (val' !? i) of
            Just e -> withFailure e xs
            _ -> Left $ "Could not get index " ++ (show i)
        _ -> Left $ "Expected JSON array for index " ++ (show i)
    Key k -> case val of  
        (Object val') -> case (HM.lookup k val') of
            Just e -> withFailure e xs
            _ -> Left $ "Could not get key " ++ (unpack k)
        _ -> Left $ "Expected JSON object for key " ++ (unpack k)

だからこれで:

-- val =  [[1,0,3], {"name" : "value"}]

> withFailure val [Nth 1, Key "name", Key "hello"]
Left "Expected JSON object for key hello"

> withFailure val [Nth 1, Key "name"]
Right (String "value")

これを行うよりエレガントな方法はありますか?lens を使用するために、Either-ish モナドを作成すると、次のようになりwithFailureます。

4

1 に答える 1