首页 > 解决方案 > 理解 Elm 中的类型解构

问题描述

我试图了解在 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)

我不明白让的正文。为什么会有这样的任务以及如何评估代码?怎么

Dict.get 关键对象

处理并“绑定”到?

decodeKey 对象 = ...

尝试解码值 = ...

从根本上说,我试图了解 let 中发生的事情,以便它为Decoder attemptToDecode返回一些“有用”的东西。另外,有没有更好的方式来表达意图?

先感谢您!

标签: elm

解决方案


我认为@zh5 提出了一个有效的观点,即:

  1. 这可能不是您在这一点上学习的正确示例(无论您要完成什么)
  2. 或者如果是,您应该能够在不问这个问题的情况下理解它。

另一方面,出于好奇而尝试理解某些东西是一件好事,即使它并不总是特别有用,所以我会尝试提供帮助。


这是field(我假设)的意图:

给我一个“逻辑”Decoder我可以用它来解码一个字段并给我一个字段名。我将从您的. _ _DecoderDecoder

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

  1. attemptToDecode捕获确保正在解码的任何内容都是 JSON 对象的逻辑。这个 JSON 对象的值表示为一个字典,该字典被提取并传递给第二部分。
    (如果正在解码的不是对象,那么结果显然应该是一个错误。)
  2. decodeKey捕获逻辑的另一半。有了字典形式的JSON对象的内容,现在我们应该找到该字段并尝试使用Decoder. 该逻辑从解码器中解构并parameterAttempt在代码中调用。
    (显然,如果在 JSON 对象中找不到该字段,则结果应该是错误。)

现在,attemptToDecode引用decodeKeywhich then 引用parameterAttempt(为解码字段传递的原始逻辑),所以我们可以说它attemptToDecode 捕获了从 JSON 对象解码字段所需的整个逻辑。所以在这一点上,需要做的就是把这个逻辑包装回 a Decoder,这正是代码所说的:

Decoder attemptToDecode


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


推荐阅读