-
Notifications
You must be signed in to change notification settings - Fork 25
Streams #266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Streams #266
Changes from all commits
19a20cd
0a246ad
25d4b85
8af41b1
64b52ca
705e387
7a4ac58
ca61e41
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,204 @@ | ||||||||||||||
| {# This file is part of DBL, released under the MIT license. | ||||||||||||||
| # See LICENSE for details. | ||||||||||||||
| #} | ||||||||||||||
|
|
||||||||||||||
| import open /Lazy | ||||||||||||||
|
|
||||||||||||||
| ## # Stream module | ||||||||||||||
|
|
||||||||||||||
| {## | ||||||||||||||
| This module provides lazy lists, also known as streams. | ||||||||||||||
| Each and every node of a stream is deferred, meaning that | ||||||||||||||
| no computation occurs unless results are forcibly read. | ||||||||||||||
|
|
||||||||||||||
| Contrary to regular lists, streams may be infinite. Some iterative | ||||||||||||||
| functions may never terminate! | ||||||||||||||
| ##} | ||||||||||||||
|
|
||||||||||||||
| rec | ||||||||||||||
| ## Stream type. | ||||||||||||||
| abstr data Stream X = Stream of Lazy (Node X) | ||||||||||||||
| data Node X = | ||||||||||||||
| | Cons of X, Stream X | ||||||||||||||
| | Nil | ||||||||||||||
| end | ||||||||||||||
|
|
||||||||||||||
| parameter X : type | ||||||||||||||
|
|
||||||||||||||
| method unstream (Stream xs) = xs | ||||||||||||||
|
|
||||||||||||||
| {## Creates stream from given list. ##} | ||||||||||||||
| pub let rec fromList (xs : List X) = | ||||||||||||||
| Stream (lazy (fn _ => | ||||||||||||||
| match xs with | ||||||||||||||
| | [] => Nil | ||||||||||||||
| | x :: xs => Cons x (fromList xs) | ||||||||||||||
| end)) : Stream X | ||||||||||||||
|
|
||||||||||||||
| {## Returns all elements of a stream as a list. ##} | ||||||||||||||
| pub let rec toList (Stream xs : Stream X) = | ||||||||||||||
| match xs.force with | ||||||||||||||
| | Nil => [] : List X | ||||||||||||||
| | Cons x xs => x :: toList xs | ||||||||||||||
| end : List X | ||||||||||||||
|
|
||||||||||||||
| {## | ||||||||||||||
| Initializes lazy stream by iteratively applying function `f` on previous results. | ||||||||||||||
|
|
||||||||||||||
| This function may generate infinite stream. | ||||||||||||||
|
Comment on lines
+46
to
+48
|
||||||||||||||
| Initializes lazy stream by iteratively applying function `f` on previous results. | |
| This function may generate infinite stream. | |
| Initializes a lazy stream by repeatedly applying function `f` to a state value. | |
| This function may generate an infinite stream. |
ppolesiuk marked this conversation as resolved.
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| import List | ||
| import Stream | ||
|
|
||
| let _ = assert {msg="fromList > toList"} | ||
| (let xs = [1, 2, 3, 4] in | ||
| xs == Stream.toList (Stream.fromList xs)) | ||
|
|
||
| let _ = assert {msg="toList > fromList"} | ||
| (let xs = Stream.cons 10 (Stream.cons 20 (Stream.empty)) in | ||
| xs == Stream.fromList (Stream.toList xs)) | ||
|
|
||
| let _ = | ||
| let f x = if 2 == x then None else Some (x, 1 + x) in | ||
| assert {msg="unfold"} | ||
| (Stream.fromList [0, 1] == Stream.unfold 0 f) | ||
|
|
||
| let _ = assert {msg="isEmpty"} (Stream.isEmpty (Stream.empty {X=Int})) | ||
| let _ = assert {msg="isEmpty"} (not (Stream.isEmpty (Stream.fromList [1]))) | ||
|
|
||
| let _ = assert {msg="singleton"} (Stream.singleton 1 == Stream.fromList [1]) | ||
|
|
||
| let _ = assert {msg="cons"} | ||
| (Stream.cons 3 (Stream.fromList [2, 1]) == Stream.fromList [3, 2, 1]) | ||
|
|
||
| let _ = assert {msg="uncons"} | ||
| match Stream.uncons (Stream.fromList [1, 2, 3]) with | ||
| | Some (x, _) => 1 == x | ||
| | None => False | ||
| end | ||
| let _ = assert {msg="uncons"} | ||
| match Stream.uncons (Stream.empty {X=Int}) with | ||
| | None => True | ||
| | _ => False | ||
| end | ||
|
|
||
| let _ = assert {msg="map"} | ||
| (Stream.fromList ["1", "2"] | ||
| == Stream.map (fn x => (x : Int).toString) (Stream.fromList [1, 2])) | ||
|
|
||
| let _ = assert {msg="append"} | ||
| (Stream.append (Stream.fromList [1, 2, 3]) (Stream.fromList [4, 5, 6]) | ||
| == Stream.fromList [1, 2, 3, 4, 5, 6]) | ||
|
|
||
| let _ = assert {msg="concatMap"} | ||
| (Stream.fromList [1, 2, 3] >.concatMap (fn (x : Int) => Stream.fromList [x + 1, x - 1]) | ||
| == Stream.fromList [2, 0, 3, 1, 4, 2]) | ||
|
|
||
| let _ = assert {msg="takeWhile"} | ||
| (Stream.takeWhile (fn (x : Int) => x <= 2) (Stream.fromList [1, 2, 3, 4, 1]) | ||
| == Stream.fromList [1, 2]) | ||
|
|
||
| let _ = assert {msg="filter"} | ||
| (Stream.filter (fn (x : Int) => x <= 2) (Stream.fromList [1, 2, 3, 4, 1]) | ||
| == Stream.fromList [1, 2, 1]) | ||
|
|
||
| let _ = assert {msg="foldRight"} | ||
| (Stream.foldRight (fn (x : Int) y => x + y) (Stream.fromList [1, 2, 3, 4]) 0 | ||
| == 10) | ||
|
|
||
| let _ = assert {msg="foldRight1Err"} | ||
| (Stream.foldRight1Err {~onError = fn _ => 42} | ||
| (fn (x : Int) y => x + y) (Stream.fromList [1, 2, 3, 4]) | ||
| == 10) | ||
| let _ = assert {msg="foldRight1Err"} | ||
| (Stream.foldRight1Err {~onError = fn _ => 42} | ||
| (fn (x : Int) y => x + y) (Stream.empty {X=Int}) | ||
| == 42) | ||
|
|
||
| let _ = assert {msg="equal"} | ||
| (Stream.equal (Stream.fromList [1, 2, 3]) (Stream.fromList [1, 2, 3])) | ||
| let _ = assert {msg="equal"} | ||
| (not (Stream.equal (Stream.fromList [1, 2, 3]) (Stream.fromList [4, 5, 6]))) |
Uh oh!
There was an error while loading. Please reload this page.