unison/unison-src/tests/stream.u
2022-12-07 11:58:32 -06:00

71 lines
1.6 KiB
Plaintext

structural ability Emit a where
emit : a ->{Emit a} ()
structural type Stream e a r = Stream ('{e, Emit a} r)
use Stream Stream
use Optional None Some
use Universal ==
-- unfold : s -> (s ->{} Optional (a, s)) -> Stream e a ()
unfold s f =
step s = match f s with
None -> ()
Some (a, s) -> emit a
step s
Stream '(step s)
run : Stream e a r ->{e, Emit a} r
run = cases Stream c -> !c
run' = cases Stream s -> s
(++) : Stream {e} a r -> Stream {e} a r -> Stream {e} a r
s1 ++ s2 = Stream '(forceBoth (run' s1) (run' s2))
from : Nat -> Stream {} Nat ()
from n = unfold n (n -> Some (n, n + 1))
-- take : Nat -> Stream {} a () -> Stream {} a ()
take n s =
step n = cases
{Emit.emit a -> k} ->
if n == 0 then ()
else
Emit.emit a
handle k () with step (drop n 1)
{r} -> ()
Stream ' handle run s with step n
-- map : (a -> b) -> Stream {e} a r -> Stream {e} b r
map f s =
step = cases
{r} -> r
{Emit.emit a -> k} ->
Emit.emit (f a)
handle k () with step
Stream ' handle run s with step
-- toSeq : Stream {e} a r ->{e} [a]
toSeq s =
step acc = cases
{Emit.emit a -> k} -> handle k () with step (snoc acc a)
{_} -> acc
handle run s with step []
fromSeq : [a] -> Stream {} a ()
fromSeq a =
step a = match List.at 0 a with
None -> None
Some h -> Some (h, drop 1 a)
unfold a step
> toSeq (take 7 (map (x -> x + 10) (from 0)))
-- > toSeq (Stream.fromSeq [1,2,3] ++ Stream.fromSeq [4,5,6])
-- > toSeq (Stream.take 20 (from 0))
-- run two thunks in sequence
forceBoth a b =
_ = !a
!b