Haskell 在Aeson解析器中展平MonadPlus

Haskell 在Aeson解析器中展平MonadPlus,haskell,composition,aeson,monadplus,Haskell,Composition,Aeson,Monadplus,我不确定我是不是找错了方向,但我有一个Aeson-FromJSON定义,它看起来相当庞大,我想知道它是否可以变得更简洁。如果URI的嵌套解析失败,我想缩短整个对象的解析 data Link = Link { link :: URI , tags :: [String] } deriving (Show, Typeable, Eq) instance FromJSON Link where parseJSON :: Va

我不确定我是不是找错了方向,但我有一个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
parseURI的类型是parseURI::String->Maybe URI,Maybe和Parser都有MonadPlus实例。有没有一种方法可以直接组合这两个元素,并在最后删除丑陋的case语句?

解析器通常更简洁,您可以使用mzero返回将Nothing转换为mzero来组合parseURI的结果

解析器通常更简洁,您可以使用mzero返回将Nothing转换为mzero来合成parseURI的结果


模式匹配可以工作,但这只在do not explicit>>=内部工作,因为会进行额外的去糖化:

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

这里发生的情况是,模式匹配左侧的失败模式匹配起作用,但这只在do not explicit>>=内部起作用,这是由于额外的去糖化:

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

这里发生的事情是,在a的左手边,一个失败的模式匹配,哦,我在一次尝试中非常接近。谢谢,这正是我想要的解决方案!哦,在我的一次尝试中,我是如此接近。谢谢,这正是我想要的解决方案!
> -- 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