1

ここで間違ったツリーを吠えているのかどうかはわかりませんが、かなりかさばるように見える Aeson のFromJSON定義があり、それをもっと簡潔なものに変えることができるかどうか疑問に思っていました。ネストされた URI の解析が失敗した場合、オブジェクト全体の解析を省略したいと考えています。

data Link = Link { link :: URI
                 , tags :: [String]
                 } deriving (Show, Typeable, Eq)

instance FromJSON Link where
    parseJSON :: Value -> Parser Link
    parseJSON (Object o) = do
        linkStr <- o .: "link"
        tags' <- o .: "tags"

        case parseURI linkStr of
            Just l -> return $ Link l tags'
            Nothing -> mzero

    parseJSON _ = mzero

の型はparseURIisparseURI :: String -> Maybe URIと bothMaybeParserhaveMonadPlusインスタンスです。2つを直接構成し、最後に醜いケースステートメントを削除する方法はありますか?

4

2 に答える 2

1

パターン マッチングは機能しますが、余分な脱糖が行われるため、do明示的ではない記法内でのみ機能します。>>=

instance FromJSON Link where
    parseJSON (Object o) = do
        Just link' <- o .: "link"
        tags'      <- o .: "tags"
        return $ Link link' tags'
    parseJSON _ = mzero

> -- Note that I used link :: String for my testing instead
> decode "{\"link\": \"test\", \"tags\": []}" :: Maybe Link
Just (Link {link = "test", tags=[]})
> decode "{\"tags\": []}" :: Maybe Link
Nothing

ここで起こっているのは、 a の左側で失敗したパターン マッチ<-が を呼び出しているということfailです。のソースを見ると、が を呼び出しているParserことがわかります。これは の実装でも使用されているため、この場合は安全です。一般的には を呼び出すだけで、モナドに応じてさまざまなことを行うことができますが、それは理にかなっていると思います。failfailDescmzerofailParser

ただし、暗黙の動作に依存しないため、@shang の回答の方が確実に優れています。

于 2015-03-19T21:55:40.433 に答える