aiken/examples/acceptance_tests/035/lib/aiken/dict.ak

61 lines
1.5 KiB
Plaintext

/// An opaque `Dict`. The type is opaque because the module maintains some
/// invariant, namely: there's only one occurence of a given key in the dictionnary.
pub opaque type Dict<key, value> {
inner: List<#(ByteArray, value)>,
}
/// Create a new map
pub fn new() -> Dict<key, value> {
Dict { inner: [] }
}
pub fn insert(
self: Dict<ByteArray, value>,
key k: ByteArray,
value v: value,
) -> Dict<key, value> {
Dict {
inner: do_insert_with(self.inner, k, v, fn(_, left, _right) { Some(left) })}
}
pub fn union_with(
left: Dict<key, value>,
right: Dict<key, value>,
with: fn(ByteArray, value, value) -> Option<value>,
) -> Dict<key, value> {
Dict { inner: do_union_with(left.inner, right.inner, with) }
}
fn do_union_with(
left: List<#(ByteArray, value)>,
right: List<#(ByteArray, value)>,
with: fn(ByteArray, value, value) -> Option<value>,
) -> List<#(ByteArray, value)> {
when left is {
[] -> right
[#(k, v), ..rest] ->
do_union_with(rest, do_insert_with(right, k, v, with), with)
}
}
fn do_insert_with(
self: List<#(ByteArray, value)>,
key k: ByteArray,
value v: value,
with: fn(ByteArray, value, value) -> Option<value>,
) -> List<#(ByteArray, value)> {
when self is {
[] -> [#(k, v)]
[#(k2, v2), ..rest] ->
if k == k2 {
when with(k, v, v2) is {
Some(combined) -> [#(k, combined), ..rest]
None -> rest
}
} else {
[#(k2, v2), ..do_insert_with(rest, k, v, with)]
}
}
}