Gozala / Gozala/decoder.flow

Add a conditional branching combinator

オープン
#2 コメント 5 件 リアクション 2 件 担当者 0 名 GitHub で見る
主要言語
JavaScript
スター
3
フォーク
0
PR マージ指標
30日以内にマージされた PR はありません

説明

Elm provides `andThen : (a -> Decoder b) -> Decoder a -> Decoder b` function to create decoders that depend on previous results. For example if you are creating versioned data, you might do something like this:

```elm
info : Decoder Info
info =
field "version" int
|> andThen infoHelp

infoHelp : Int -> Decoder Info
infoHelp version =
case version of
4 ->
infoDecoder4

3 ->
infoDecoder3

_ ->
fail <|
"Trying to decode info, but version "
++ toString version ++ " is not supported."

-- infoDecoder4 : Decoder Info
-- infoDecoder3 : Decoder Info
```

decoder.flow does not provide `andThen` as it would make serialization and transfer of decoders across the threads impossible. Although similar to how `Decoder.record` and `Decoder.form` provide a way to address same use cases as `map`, `map2`, ...`map8` in Elm we could provide some solution to addressing `andThen` use cases like the one above. For instance `match` like combinator could be implemented:

```js
const version = Decoder.field("version", Decoder.Integer)
Decoder.either(
Decoder.when(version, Decoder.ok(4), infoDecoder4)
Decoder.when(version, Decoder.ok(3), infoDecoder3)
Decoder.error("Trying to decode info, but provided version isn't supported"))
```

Note that in comparison to `andThen` this is far more limited and even this example unlike original Elm code is unable to include encountered version in the error message, but it still might enable certain use cases that aren't possible today.

Primary limitation of this would be that unlike `andThen` result can't be carried over to the next decoder, but maybe that could be worked around like in the example below:

```js
const versionedInfo = Decoder.form({
version: Decoder.field("version", Decoder.Integer)
info: Decoder.value
})

const infoHelp = Decoder.either(
Decoder.record({ version: Decoder.ok(4), ok: infoDecoder4 }),
Decoder.record({ version: Decoder.ok(3), ok: infoDecoder3 }),
Decoder.record({ version: Decoder.Integer, error: Decoder.ok('Invalid version') }))

const info = Decoder.chain(versionedInfo, infoHelp)
```

P.S.: We currently have no `Decoder.value` nor `Decoder.chain` but they could be easily added.

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

まず、提案されている Decoder.when、Decoder.either、Decoder.value、Decoder.chain の設計を、既存の Decoder.record と Decoder.form の動作と比較します。デコーダーをシリアライズしたりスレッド間で転送したりできなくすることなく、どの条件分岐のユースケースをサポートできるかを判断します。無効なバージョンをどのように扱うかを含め、合意された API と実装範囲が決まれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
javascript
領域
data
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
説明が足りない
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。