Last active
May 15, 2024 06:21
-
-
Save tynanbe/6ee681eb95c14c1ec7da7f63bd3492d8 to your computer and use it in GitHub Desktop.
Proposed Gleam tuple spread syntax
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import gleam/dynamic.{DecodeErrors, Dynamic, field, int, list, string} | |
import gleam/io | |
import gleam/json | |
import gleam/list | |
import gleam/result | |
type DynResult(a) = | |
Result(a, DecodeErrors) | |
pub opaque type Collector(a) { | |
Collector(data: Dynamic, result: DynResult(a)) | |
} | |
pub fn collector(data: Dynamic) -> Collector(#()) { | |
Collector(data: data, result: Ok(#())) | |
} | |
// Spread tuple type's elements into another tuple type | |
pub fn get( | |
from prev: Collector(a), | |
with decoder: fn(Dynamic) -> DynResult(b), | |
) -> Collector(#(..a, b)) { | |
let Collector(data, result) = prev | |
case decoder(data), result { | |
Ok(value), Ok(tuple) -> | |
// Spread tuple's elements into another tuple | |
#(..tuple, value) | |
|> Ok | |
Error(new_errors), Error(errors) -> | |
errors | |
|> list.append(new_errors) | |
|> Error | |
Error(errors), _ | _, Error(errors) -> Error(errors) | |
} | |
|> Collector(data: data) | |
} | |
pub fn apply( | |
from prev: Collector(a), | |
// Spread tuple type's elements into fn type's parameters | |
to constructor: fn(..a) -> b, | |
) -> DynResult(b) { | |
use args <- result.map(over: prev.result) | |
// Spread tuple's elements into fn's arguments | |
constructor(..args) | |
} | |
/// Begin Demo | |
pub type FooBar { | |
FooBar(foo: Int, bar: String) | |
} | |
pub fn decode_foobar(data: Dynamic) -> DynResult(FooBar) { | |
collector(data) | |
|> get(field("foo", of: int)) | |
|> get(field("bar", of: string)) | |
|> apply(to: FooBar) | |
} | |
pub fn decode_foobars(data: String) -> Result(List(FooBar), json.DecodeError) { | |
let decoder = list(of: decode_foobar) | |
json.decode(from: data, using: decoder) | |
} | |
pub fn main() { | |
let data = | |
" | |
[ | |
{ | |
\"foo\" : 0, | |
\"bar\" : \"a\" | |
}, | |
{ | |
\"foo\" : 1, | |
\"bar\" : \"b\" | |
} | |
] | |
" | |
data | |
|> decode_foobars | |
|> io.debug | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment