{{
A data structure that holds the arguments that you would pass to foldLeft.
The one difference is that there is an extra "extract" function at the end that is to be run after
the foldLeft completes. This can be useful when the fold needs to maintain some state during the
fold but you don't want to include it in the final result.
}}
unique type Fold' g a b x = Fold' (x -> {g} a -> {g} x) x (x -> {g} b)
{{
This is essentially a {Fold'} where the `x` type parameter is an existential type.
Because Unison doesn't directly support existential types, there is a bit of noise required to
craft them from universal type parameters.
}}
unique type Fold g a b = Fold (∀ g2 r. (∀ x. Fold' g a b x -> {g2} r) -> {g2} r)
Fold.fromFold' : Fold' g a b x -> Fold g a b
Fold.fromFold' fold = Fold.Fold (f -> f fold)
{{ Helper function for creating a {type Fold} without manually constructing a {type Fold'}}}
Fold.mkFold : (t -> {g} a -> {g} t) -> t -> (t -> {g} b) -> Fold g a b
Fold.mkFold step init extract =
Fold.fromFold' (Fold'.Fold' step init extract)
{{ Check whether the predicate holds for all elements }}
folds.all : (a -> {g} Boolean) -> Fold g a Boolean
folds.all predicate =
Fold.mkFold (b -> a -> b && (predicate a)) true id
{{ Run a fold on a {type .base.Stream}}}
Fold.Stream.fold : Fold g a b -> '{g, Stream a} r -> '{g} b
Fold.Stream.fold =
run: Fold' g a b x -> '{g, Stream a} r -> '{g} b
run =
cases Fold'.Fold' step init extract -> stream -> _ -> extract !(.base.Stream.fold step init stream)
cases
Fold f -> stream -> f (f' -> run f' stream)
.> add
Now the following code compiles, but when run via test>
results in the runtime error applying non-function: Enum ##Boolean 1
:
folds.all.tests.stream =
pred = n -> (n Nat.> 2)
res : 'Boolean
res = Fold.Stream.fold (folds.all pred) (Stream.range 1 5)
check (!res Universal.== false)
However, similar code using List
works just fine. So it would seem that the issue arises somewhere with abilities and/or delayed thunks.
Fold.List.fold : Fold g a b -> [a] -> {g} b
Fold.List.fold =
run: Fold' g a b x -> [a] -> {g} b
run =
cases Fold'.Fold' step init extract -> as -> extract (.base.List.foldLeft step init as)
cases
Fold.Fold f -> as -> f (f' -> run f' as)
test> folds.all.tests.list =
pred = n -> (n Nat.> 2)
res : Boolean
res = Fold.List.fold (folds.all pred) [1, 2, 3, 4, 5]
check (res Universal.== false)