Created
August 14, 2020 22:15
-
-
Save Pet3ris/6918587f9dc39a79d92852819aa3815e to your computer and use it in GitHub Desktop.
Lazy promise queue implementation in ReasonML
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Lazy PromiseQueue implementation | |
type pair('a) = ('a, t('a)) | |
and t('a) = {next: Lazy.t(Js.Promise.t(option(pair('a))))}; | |
let build = promise => {next: promise}; | |
let empty: t('a) = lazy(Js.Promise.resolve(None)) |> build; | |
let cons = (p: Lazy.t(Js.Promise.t('a)), pq: t('a)) => { | |
lazy(p |> Lazy.force |> Js.Promise.then_(a => Js.Promise.resolve(Some((a, pq))))) |> build; | |
}; | |
let make = (p: Lazy.t(Js.Promise.t('a))): t('a) => cons(p, empty); | |
let next = (pq: t('a)): Lazy.t(Js.Promise.t(option(pair('a)))) => pq.next; | |
let rec before = (p: t('a), q: t('a)): t('a) => | |
lazy(p.next | |
|> Lazy.force | |
|> Js.Promise.then_(ppair => | |
switch (ppair) { | |
| Some((first, pq)) => | |
Js.Promise.resolve(Some((first, before(pq, q)))) | |
| None => q.next |> Lazy.force | |
} | |
)) | |
|> build; | |
let rec fromArrayP = (all: array(Lazy.t(Js.Promise.t('a)))): t('a) => { | |
switch (Belt.Array.get(all, 0)) { | |
| Some(first) => cons(first, fromArrayP(Belt.Array.sliceToEnd(all, 1))) | |
| None => empty | |
}; | |
}; | |
let rec mapP = (pq: t('a), f: 'a => Lazy.t(Js.Promise.t('b))): t('b) => | |
lazy(pq.next | |
|> Lazy.force | |
|> Js.Promise.then_(ppair => | |
switch (ppair) { | |
| Some((first, pq)) => | |
let rest = mapP(pq, f); | |
first | |
|> f | |
|> Lazy.force | |
|> Js.Promise.then_(first => | |
Js.Promise.resolve(Some((first, rest))) | |
); | |
| None => Js.Promise.resolve(None) | |
} | |
)) | |
|> build; | |
let rec flatMapP = (pq: t('a), f: 'a => array(Lazy.t(Js.Promise.t('b)))): t('b) => | |
lazy(pq.next | |
|> Lazy.force | |
|> Js.Promise.then_(ppair => | |
switch (ppair) { | |
| Some((first, pq)) => | |
let rest = flatMapP(pq, f); | |
first -> f -> fromArrayP -> (firsts => before(firsts, rest).next) -> Lazy.force; | |
| None => Js.Promise.resolve(None) | |
} | |
)) | |
|> build; | |
let rec take = (pq: t('a), n: int): Js.Promise.t(array('a)) => | |
if (n == 0) { | |
Js.Promise.resolve([||]); | |
} else { | |
pq.next | |
|> Lazy.force | |
|> Js.Promise.then_(ppair => | |
switch (ppair) { | |
| Some((first, pq)) => | |
let a = [|first|]; | |
take(pq, n - 1) | |
|> Js.Promise.then_(rest => | |
Js.Promise.resolve(Belt.Array.concat(a, rest)) | |
); | |
| None => Js.Promise.resolve([||]) | |
} | |
); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type t('a); | |
let fromArrayP: array(Lazy.t(Js.Promise.t('a))) => t('a); | |
let mapP: (t('a), 'a => Lazy.t(Js.Promise.t('b))) => t('b); | |
let flatMapP: (t('a), 'a => array(Lazy.t(Js.Promise.t('b)))) => t('b); | |
let take: (t('a), int) => Js.Promise.t(array('a)); | |
// Example use: | |
// let output = arrayOfNumbers | |
// -> PromiseQueue.fromArrayP | |
// -> PromiseQueue.flatMapP(f) | |
// -> PromiseQueue.mapP(f) | |
// -> PromiseQueue.take(20) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment