理解Elm中的类型分解

理解Elm中的类型分解,elm,Elm,我试图理解在Elm中定义类型和模式匹配的所有不同方式 在搜索可供学习的代码时,我在纯Elm中找到了一个JSON解码器的实现。代码可以在文章系列中找到 我无法理解字段函数中使用的样式: type Value = Jnull | Jobject (Dict String Value) type Decoder a = Decoder (Value -> Result String a) decodeValue : Decoder a -> Value ->

我试图理解在Elm中定义类型和模式匹配的所有不同方式

在搜索可供学习的代码时,我在纯Elm中找到了一个JSON解码器的实现。代码可以在文章系列中找到

我无法理解字段函数中使用的样式:

type Value
    = Jnull
    | Jobject (Dict String Value)

type Decoder a
    = Decoder (Value -> Result String a)

decodeValue : Decoder a -> Value -> Result String a
decodeValue (Decoder attemptToDecode) value =
    attemptToDecode value

field : String -> Decoder a -> Decoder a
field key (Decoder parameterAttempt) =
    let
        decodeKey object =
            Dict.get key object
                |> Result.fromMaybe "couldn't find key"
                |> Result.andThen parameterAttempt

        attemptToDecode value =
            case value of
                Jobject foundIt ->
                    decodeKey foundIt

                _ ->
                    Err "not an object"
    in
        Decoder attemptToDecode
为函数编写的测试如下所示:

test "decodes a field" <|
            \_ ->
                Jobject (Dict.singleton "nested" (Jnumber 5.0))
                    |> decodeValue (field "nested" int)
                    |> Expect.equal (Ok 5)
测试“解码字段”
Jobject(Dict.singleton“嵌套”(Jnumber 5.0))
|>解码值(字段“嵌套”int)
|>Expect.equal(Ok 5)
我不明白出租汽车的车身。为什么会有这样的赋值?代码是如何计算的?怎么样

Dict.get键对象

处理并“绑定”到

decodeKey对象=

attemptToDecode值=

从根本上说,我试图理解let中发生了什么,以便它返回一些对解码器尝试进行解码的“有用”信息。还有,是否有更好的方式表达意图


提前谢谢你

解码器类型定义为:

type Decoder a
    = Decoder (Value -> Result String a)
有一个数据构造函数接受一个参数。这意味着为了构建解码器,我们需要一个函数,该函数接受一个值并返回一个结果字符串a:

f: Value -> Result String a -> Decoder a
let中的赋值是构建函数,用作构建块。阅读它们的类型定义可以让事情更清楚

let
    decodeKey: Dict String Value -> Result String a
    decodeKey object =
        case Dict.get key object of
            Just value ->
                parameterAttempt value

            Nothing ->
                Err "couldn't find key"

    attemptToDecode: Value -> Result String a
    attemptToDecode value =
        case value of
            Jobject foundIt ->
                decodeKey foundIt

            _ ->
                Err "not an object"
in
    Decoder attemptToDecode
尝试进行解码使用解码键并且可以这样做,因为两者都返回

结果字符串a


非常感谢您对此的任何反馈。

我认为@zh5的观点是正确的,即:

  • 在这一点上,这可能不是你学习的正确例子(无论你想完成什么)
  • 或者,如果是,你应该能够理解它,而不必问这个问题
  • 另一方面,仅仅出于好奇去理解一些东西是一件好事,即使它并不总是特别有用,所以我会尽力帮助你


    这是
    字段
    的意图(我假设):

    给我一个
    解码器中的“逻辑”,我可以用它来解码一个字段
    给我一个字段名。我将从您的
    解码器
    中取出“逻辑”, 在上面添加一些“额外的逻辑”来查找 JSON对象中的字段,我将返回此字段 新的
    解码器中的逻辑

    因此,“额外逻辑”在上述代码中分为两部分:

  • attemptodecode
    捕获用于确保被解码的对象是JSON对象的逻辑。这个JSON对象的值表示为一个字典,该字典被提取并传递给第二部分
    (如果被解码的东西不是对象,那么结果显然应该是错误的。)
  • decodeKey
    捕获逻辑的另一半。将JSON对象的内容设置为字典的形式,现在我们应该找到字段并尝试使用
    解码器中提供的“逻辑”对其进行解码。此逻辑从解码器中解构,并在代码中称为
    parametertest

    (显然,如果在JSON对象中找不到该字段,则结果应该是错误的。)
  • 现在,
    attemptodecode
    指的是
    decodeKey
    ,然后它指的是
    ParameterTest
    (用于解码字段的原始逻辑),因此我们可以说
    attemptodecode
    捕获了从JSON对象解码字段所需的全部逻辑。因此,在这一点上,需要做的就是将此逻辑包装回
    解码器中,这正是代码所说的:

    解码器试图解码



    当然,你自己的回答是正确的,解码器中捕获的逻辑是以函数的形式捕获的,当这些函数相互引用时,它们的类型签名必须在最后匹配。

    在我看来,你看到的示例比你的理解允许的更复杂,然后问一个在这里没有意义的问题,可能对其他人没有帮助。因为这个原因,我将不得不投票结束
    decodeKey对象
    定义了一个名为
    decodeKey
    的函数,其参数
    object
    由下面的代码实现
    |>
    是介绍文档中介绍的管道操作符。
    Dict.get key object
    的结果通过管道传输到下面的代码。所有这些都是
    decodeKey
    的实现。