Skip to content

Instantly share code, notes, and snippets.

@schurhammer
Created October 20, 2023 05:33
Show Gist options
  • Save schurhammer/9cfa3493bb5387632dff70ae46afd864 to your computer and use it in GitHub Desktop.
Save schurhammer/9cfa3493bb5387632dff70ae46afd864 to your computer and use it in GitHub Desktop.
decoder stuff
import gleam/dynamic.{DecodeError, Dynamic}
import gleam/list
import gleam/io
type Foo {
Foo(Int, Float, String)
}
pub opaque type Collector(dynamic, a, b) {
Collector(data: dynamic, result: Result(a, List(DecodeError)), prev: b)
}
fn begin(data: dynamic) {
Collector(data: data, result: Ok(Nil), prev: Nil)
}
fn then(
prev: Collector(dynamic, a, b),
decode: fn(dynamic) -> Result(val, List(DecodeError)),
) -> Collector(dynamic, val, Collector(dynamic, a, b)) {
case decode(prev.data), prev.result {
Ok(x), Ok(_) -> Collector(data: prev.data, result: Ok(x), prev: prev)
Error(x), Error(y) ->
Collector(data: prev.data, result: Error(list.append(x, y)), prev: prev)
Error(x), _ -> Collector(data: prev.data, result: Error(x), prev: prev)
_, Error(y) -> Collector(data: prev.data, result: Error(y), prev: prev)
}
}
fn unwrap(
collector: Collector(dynamic, a, b),
cb: fn(a, b) -> Result(c, List(DecodeError)),
) -> Result(c, List(DecodeError)) {
case collector.result {
Ok(x) -> cb(x, collector.prev)
Error(x) -> Error(x)
}
}
fn example(data: Dynamic) -> Result(Foo, List(DecodeError)) {
let collector =
begin(data)
|> then(dynamic.element(0, dynamic.int))
|> then(dynamic.element(1, dynamic.float))
|> then(dynamic.element(2, dynamic.string))
use e2, collector <- unwrap(collector)
use e1, collector <- unwrap(collector)
use e0, _collector <- unwrap(collector)
Ok(Foo(e0, e1, e2))
}
pub fn main() {
#(0, 1.0, "2")
|> dynamic.from
|> example()
|> io.debug()
#(Nil, 1.0, "2")
|> dynamic.from
|> example()
|> io.debug()
#(0, Nil, "2")
|> dynamic.from
|> example()
|> io.debug()
#(0, 1.0, Nil)
|> dynamic.from
|> example()
|> io.debug()
#(Nil, Nil, "2")
|> dynamic.from
|> example()
|> io.debug()
#(Nil, 1.0, Nil)
|> dynamic.from
|> example()
|> io.debug()
#(0, Nil, Nil)
|> dynamic.from
|> example()
|> io.debug()
#(Nil, Nil, Nil)
|> dynamic.from
|> example()
|> io.debug()
Nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment