Skip to content

Commit 51bc926

Browse files
committed
introduce type-alias and simplify the API.
1 parent 2d6db56 commit 51bc926

File tree

3 files changed

+80
-73
lines changed

3 files changed

+80
-73
lines changed

lib/aiken/collection/dict.ak

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//// > [`dict.from_ascending_list`](#from_ascending_list).
1414

1515
use aiken/builtin
16+
use aiken/collection/dict/union.{UnionStrategy}
1617

1718
/// An opaque `Dict`. The type is opaque because the module maintains some
1819
/// invariant, namely: there's only one occurrence of a given key in the dictionary.
@@ -755,16 +756,14 @@ pub fn insert_with_alt(
755756
self: Dict<key, value>,
756757
key k: ByteArray,
757758
value v: value,
758-
with: fn(ByteArray, value, value) ->
759-
fn(fn(value) -> Pairs<ByteArray, value>, fn() -> Pairs<ByteArray, value>) ->
760-
Pairs<ByteArray, value>,
759+
with: UnionStrategy<ByteArray, value>,
761760
) -> Dict<key, value> {
762761
Dict {
763762
inner: do_insert_with_alt(
764763
self.inner,
765764
k,
766765
v,
767-
fn(k, v1, v2) { with(k, v2, v1) },
766+
fn(k, v1, v2, some, none) { with(k, v2, v1, some, none) },
768767
),
769768
}
770769
}
@@ -783,13 +782,10 @@ test insert_with_1() {
783782
}
784783

785784
test insert_with_alt_1() {
786-
let sum =
787-
fn(_k, a, b) { fn(som, _non) { som(a + b) } }
788-
789785
let result =
790786
empty
791-
|> insert_with_alt(key: "foo", value: 1, with: sum)
792-
|> insert_with_alt(key: "bar", value: 2, with: sum)
787+
|> insert_with_alt(key: "foo", value: 1, with: union.sum())
788+
|> insert_with_alt(key: "bar", value: 2, with: union.sum())
793789
|> to_pairs()
794790

795791
result == [Pair("bar", 2), Pair("foo", 1)]
@@ -1050,9 +1046,7 @@ pub fn union_with(
10501046
pub fn union_with_alt(
10511047
left: Dict<key, value>,
10521048
right: Dict<key, value>,
1053-
with: fn(ByteArray, value, value) ->
1054-
fn(fn(value) -> Pairs<ByteArray, value>, fn() -> Pairs<ByteArray, value>) ->
1055-
Pairs<ByteArray, value>,
1049+
with: UnionStrategy<ByteArray, value>,
10561050
) -> Dict<key, value> {
10571051
Dict { inner: do_union_with_alt(left.inner, right.inner, with) }
10581052
}
@@ -1072,9 +1066,7 @@ fn do_union_with(
10721066
fn do_union_with_alt(
10731067
left: Pairs<ByteArray, value>,
10741068
right: Pairs<ByteArray, value>,
1075-
with: fn(ByteArray, value, value) ->
1076-
fn(fn(value) -> Pairs<ByteArray, value>, fn() -> Pairs<ByteArray, value>) ->
1077-
Pairs<ByteArray, value>,
1069+
with: UnionStrategy<ByteArray, value>,
10781070
) -> Pairs<ByteArray, value> {
10791071
when left is {
10801072
[] -> right
@@ -1111,9 +1103,7 @@ fn do_insert_with_alt(
11111103
self: Pairs<ByteArray, value>,
11121104
key k: ByteArray,
11131105
value v: value,
1114-
with: fn(ByteArray, value, value) ->
1115-
fn(fn(value) -> Pairs<ByteArray, value>, fn() -> Pairs<ByteArray, value>) ->
1116-
Pairs<ByteArray, value>,
1106+
with: UnionStrategy<ByteArray, value>,
11171107
) -> Pairs<ByteArray, value> {
11181108
when self is {
11191109
[] -> [Pair(k, v)]
@@ -1122,7 +1112,10 @@ fn do_insert_with_alt(
11221112
[Pair(k, v), ..self]
11231113
} else {
11241114
if k == k2 {
1125-
with(k, v, v2)(
1115+
with(
1116+
k,
1117+
v,
1118+
v2,
11261119
fn(combined) { [Pair(k, combined), ..rest] },
11271120
fn() { rest },
11281121
)

lib/aiken/collection/dict/union.ak

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/// A strategy for combining two values in a dictionnary that belong to the same key.
2+
pub type UnionStrategy<key, value> =
3+
fn(key, value, value, KeepValue<key, value>, DiscardValue<key, value>) ->
4+
Pairs<key, value>
5+
6+
/// A callback to keep a combined valueat a given key
7+
pub type KeepValue<key, value> =
8+
fn(value) -> Pairs<key, value>
9+
10+
/// A callback to discard a value at a given key
11+
pub type DiscardValue<key, value> =
12+
fn() -> Pairs<key, value>
13+
14+
/// A strategy which always fail, enforcing the dict contains no duplicate.
15+
pub fn expect_no_duplicate() -> UnionStrategy<key, value> {
16+
fn(_, _, _, _, _) {
17+
fail @"unexpected duplicate key found in dict."
18+
}
19+
}
20+
21+
/// Combine values by keeping the values present in the left-most dict.
22+
pub fn keep_left() -> UnionStrategy<key, value> {
23+
fn(_key, left, _right, keep, _discard) { keep(left) }
24+
}
25+
26+
/// Combine values by keeping the values present in the left-most dict.
27+
pub fn keep_right() -> UnionStrategy<key, value> {
28+
fn(_key, _left, right, keep, _discard) { keep(right) }
29+
}
30+
31+
/// Combine values by taking their sum.
32+
pub fn sum() -> UnionStrategy<key, Int> {
33+
fn(_key, left, right, keep, _discard) { keep(left + right) }
34+
}
35+
36+
/// Combine values by taking their sum, only if it is non-null. Otherwise,
37+
/// discard the key/value entirely.
38+
pub fn sum_if_non_zero() -> UnionStrategy<key, Int> {
39+
fn(_key, left, right, keep, discard) {
40+
let value = left + right
41+
if value == 0 {
42+
discard()
43+
} else {
44+
keep(value)
45+
}
46+
}
47+
}

lib/cardano/assets.ak

Lines changed: 21 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use aiken/builtin
22
use aiken/collection/dict.{Dict, from_ascending_pairs_with}
3+
use aiken/collection/dict/union
34
use aiken/collection/list
45
use aiken/crypto.{Blake2b_224, Hash, Script}
56
use aiken/option
@@ -77,14 +78,7 @@ pub fn from_asset_list(xs: Pairs<PolicyId, Pairs<AssetName, Int>>) -> Value {
7778
expect Pair(p, [_, ..] as x) = inner
7879
x
7980
|> from_ascending_pairs_with(fn(v) { v != 0 })
80-
|> dict.insert_with_alt(
81-
acc,
82-
p,
83-
_,
84-
fn(_, _, _) {
85-
fail @"Duplicate policy in the asset list."
86-
},
87-
)
81+
|> dict.insert_with_alt(acc, p, _, union.expect_no_duplicate())
8882
},
8983
)
9084
|> Value
@@ -555,30 +549,19 @@ pub fn add(
555549
self
556550
} else {
557551
let helper =
558-
fn(_, left, _right) {
559-
fn(som, non) {
560-
let inner_result =
561-
dict.insert_with_alt(
562-
left,
563-
asset_name,
564-
quantity,
565-
fn(_k, ql, qr) {
566-
fn(som, non) {
567-
let q = ql + qr
568-
if q == 0 {
569-
non()
570-
} else {
571-
som(q)
572-
}
573-
}
574-
},
575-
)
576-
577-
if dict.is_empty(inner_result) {
578-
non()
579-
} else {
580-
som(inner_result)
581-
}
552+
fn(_, left, _right, keep, discard) {
553+
let inner_result =
554+
dict.insert_with_alt(
555+
left,
556+
asset_name,
557+
quantity,
558+
union.sum_if_non_zero(),
559+
)
560+
561+
if dict.is_empty(inner_result) {
562+
discard()
563+
} else {
564+
keep(inner_result)
582565
}
583566
}
584567

@@ -638,28 +621,12 @@ pub fn merge(left v0: Value, right v1: Value) -> Value {
638621
dict.union_with_alt(
639622
v0.inner,
640623
v1.inner,
641-
fn(_, a0, a1) {
642-
fn(som, non) {
643-
let result =
644-
dict.union_with_alt(
645-
a0,
646-
a1,
647-
fn(_, q0, q1) {
648-
fn(som, non) {
649-
let q = q0 + q1
650-
if q == 0 {
651-
non()
652-
} else {
653-
som(q)
654-
}
655-
}
656-
},
657-
)
658-
if dict.is_empty(result) {
659-
non()
660-
} else {
661-
som(result)
662-
}
624+
fn(_, a0, a1, keep, discard) {
625+
let result = dict.union_with_alt(a0, a1, union.sum_if_non_zero())
626+
if dict.is_empty(result) {
627+
discard()
628+
} else {
629+
keep(result)
663630
}
664631
},
665632
),

0 commit comments

Comments
 (0)