elm - 理解 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返回一些“有用”的东西。另外,有没有更好的方式来表达意图?
先感谢您!
解决方案
我认为@zh5 提出了一个有效的观点,即:
- 这可能不是您在这一点上学习的正确示例(无论您要完成什么)
- 或者如果是,您应该能够在不问这个问题的情况下理解它。
另一方面,出于好奇而尝试理解某些东西是一件好事,即使它并不总是特别有用,所以我会尝试提供帮助。
这是field
(我假设)的意图:
给我一个“逻辑”,
Decoder
我可以用它来解码一个字段并给我一个字段名。我将从您的. _ _Decoder
Decoder
因此,“额外逻辑”在上面的代码中分为两部分:
attemptToDecode
捕获确保正在解码的任何内容都是 JSON 对象的逻辑。这个 JSON 对象的值表示为一个字典,该字典被提取并传递给第二部分。
(如果正在解码的不是对象,那么结果显然应该是一个错误。)decodeKey
捕获逻辑的另一半。有了字典形式的JSON对象的内容,现在我们应该找到该字段并尝试使用Decoder
. 该逻辑从解码器中解构并parameterAttempt
在代码中调用。
(显然,如果在 JSON 对象中找不到该字段,则结果应该是错误。)
现在,attemptToDecode
引用decodeKey
which then 引用parameterAttempt
(为解码字段传递的原始逻辑),所以我们可以说它attemptToDecode
捕获了从 JSON 对象解码字段所需的整个逻辑。所以在这一点上,需要做的就是把这个逻辑包装回 a Decoder
,这正是代码所说的:
Decoder attemptToDecode
而且,您自己的回答肯定是正确的,解码器中捕获的逻辑是以函数的形式捕获的,当这些函数相互引用时,它们的类型签名必须在最后匹配。