由于其中一个字段具有相同类型,我如何实现一个调用自身的解码器?

How do I implement a decoder that calls itself due to one of its fields having the same type?

我如何实现一个解码器,由于其字段之一具有相同类型而调用自身?

providerDecoder : Decoder JsonProvider
providerDecoder =
    Decode.map6 JsonProvider
        (field "Profile" profileDecoder)
        (field "Topics" <| Decode.list topicDecoder)
        (field "Links" <| linksDecoder)
        (field "RecentLinks" <| Decode.list linkDecoder)
        (field "Subscriptions" <| Decode.list providerDecoder)
        (field "Followers" <| Decode.list providerDecoder)

以下几行引起了问题:

(field "Subscriptions" <| Decode.list providerDecoder)
(field "Followers" <| Decode.list providerDecoder)

providerDecoder is defined directly in terms of itself, causing an infinite

总之,我不确定如何在保留 JsonProvider 类型的同时解决此错误。

附录:

type JsonProvider
    = JsonProvider
        { profile : JsonProfile
        , topics : List JsonTopic
        , links : JsonLinks
        , recentLinks : List JsonLink
        , subscriptions : List JsonProvider
        , followers : List JsonProvider
        }

编写递归JSON解码器时,通常必须依赖Json.Decode.lazy。你可以这样写这两行:

(field "Subscriptions" <| Decode.list (Decode.lazy (\_ -> providerDecoder)))
(field "Followers" <| Decode.list (Decode.lazy (\_ -> providerDecoder)))

一旦你改变它,你会看到另一条关于类型不匹配的错误消息弹出,那是因为你使用的是一个构造函数联合类型,它有一个记录作为参数(这在编写时是必需的递归记录类型)。在这种情况下,我通常像这样分离构造函数和记录类型:

type JsonProvider
    = JsonProvider JsonProviderFields

type alias JsonProviderFields =
    { profile : JsonProfile
    , topics : List JsonTopic
    , links : JsonLinks
    , recentLinks : List JsonLink
    , subscriptions : List JsonProvider
    , followers : List JsonProvider
    }

现在您可以重写提供程序解码器以首先解码 JsonProviderFields 记录,然后将其映射到 JsonProvider:

providerDecoder : Decoder JsonProvider
providerDecoder =
    Decode.map6 JsonProviderFields
        (field "Profile" profileDecoder)
        (field "Topics" <| Decode.list topicDecoder)
        (field "Links" <| linksDecoder)
        (field "RecentLinks" <| Decode.list linkDecoder)
        (field "Subscriptions" <| Decode.list (Decode.lazy (\_ -> providerDecoder)))
        (field "Followers" <| Decode.list (Decode.lazy (\_ -> providerDecoder)))
        |> Decode.map JsonProvider