Optimize stdlib (#215)
This commit is contained in:
parent
34c10e1518
commit
13bc821211
@ -19,18 +19,28 @@ namespace List =
|
|||||||
[x] => Some(x)
|
[x] => Some(x)
|
||||||
_::t => last(t)
|
_::t => last(t)
|
||||||
|
|
||||||
|
function drop_last(l : list('a)) : option(list('a)) = switch(l)
|
||||||
|
[] => None
|
||||||
|
_ => Some(drop_last_unsafe(l))
|
||||||
|
|
||||||
|
function drop_last_unsafe(l : list('a)) : list('a) = switch(l)
|
||||||
|
[_] => []
|
||||||
|
h::t => h::drop_last_unsafe(t)
|
||||||
|
[] => abort("drop_last_unsafe: list empty")
|
||||||
|
|
||||||
function find(p : 'a => bool, l : list('a)) : option('a) = switch(l)
|
function find(p : 'a => bool, l : list('a)) : option('a) = switch(l)
|
||||||
[] => None
|
[] => None
|
||||||
h::t => if(p(h)) Some(h) else find(p, t)
|
h::t => if(p(h)) Some(h) else find(p, t)
|
||||||
|
|
||||||
function find_indices(p : 'a => bool, l : list('a)) : list(int) = find_indices_(p, l, 0, [])
|
function find_indices(p : 'a => bool, l : list('a)) : list(int) = find_indices_(p, l, 0)
|
||||||
private function find_indices_( p : 'a => bool
|
private function find_indices_( p : 'a => bool
|
||||||
, l : list('a)
|
, l : list('a)
|
||||||
, n : int
|
, n : int
|
||||||
, acc : list(int)
|
|
||||||
) : list(int) = switch(l)
|
) : list(int) = switch(l)
|
||||||
[] => reverse(acc)
|
[] => []
|
||||||
h::t => find_indices_(p, t, n+1, if(p(h)) n::acc else acc)
|
h::t =>
|
||||||
|
let rest = find_indices_(p, t, n+1)
|
||||||
|
if(p(h)) n::rest else rest
|
||||||
|
|
||||||
function nth(n : int, l : list('a)) : option('a) =
|
function nth(n : int, l : list('a)) : option('a) =
|
||||||
switch(l)
|
switch(l)
|
||||||
@ -52,39 +62,40 @@ namespace List =
|
|||||||
|
|
||||||
function from_to(a : int, b : int) : list(int) = [a..b]
|
function from_to(a : int, b : int) : list(int) = [a..b]
|
||||||
|
|
||||||
function from_to_step(a : int, b : int, s : int) : list(int) = from_to_step_(a, b, s, [])
|
function from_to_step(a : int, b : int, s : int) : list(int) =
|
||||||
private function from_to_step_(a, b, s, acc) =
|
from_to_step_(a, b - (b-a) mod s, s, [])
|
||||||
if (a > b) reverse(acc) else from_to_step_(a + s, b, s, a :: acc)
|
private function from_to_step_(a : int, b : int, s : int, acc : list(int)) : list(int) =
|
||||||
|
if(b < a) acc
|
||||||
|
else from_to_step_(a, b - s, s, b::acc)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Unsafe. Replaces `n`th element of `l` with `e`. Crashes on over/underflow */
|
/* Unsafe. Replaces `n`th element of `l` with `e`. Crashes on over/underflow */
|
||||||
function replace_at(n : int, e : 'a, l : list('a)) : list('a) =
|
function replace_at(n : int, e : 'a, l : list('a)) : list('a) =
|
||||||
if(n<0) abort("insert_at underflow") else replace_at_(n, e, l, [])
|
if(n<0) abort("insert_at underflow") else replace_at_(n, e, l)
|
||||||
private function replace_at_(n : int, e : 'a, l : list('a), acc : list('a)) : list('a) =
|
private function replace_at_(n : int, e : 'a, l : list('a)) : list('a) =
|
||||||
switch(l)
|
switch(l)
|
||||||
[] => abort("replace_at overflow")
|
[] => abort("replace_at overflow")
|
||||||
h::t => if (n == 0) reverse(e::acc) ++ t
|
h::t => if (n == 0) e::t
|
||||||
else replace_at_(n-1, e, t, h::acc)
|
else h::replace_at_(n-1, e, t)
|
||||||
|
|
||||||
/* Unsafe. Adds `e` to `l` to be its `n`th element. Crashes on over/underflow */
|
/* Unsafe. Adds `e` to `l` to be its `n`th element. Crashes on over/underflow */
|
||||||
function insert_at(n : int, e : 'a, l : list('a)) : list('a) =
|
function insert_at(n : int, e : 'a, l : list('a)) : list('a) =
|
||||||
if(n<0) abort("insert_at underflow") else insert_at_(n, e, l, [])
|
if(n<0) abort("insert_at underflow") else insert_at_(n, e, l)
|
||||||
private function insert_at_(n : int, e : 'a, l : list('a), acc : list('a)) : list('a) =
|
private function insert_at_(n : int, e : 'a, l : list('a)) : list('a) =
|
||||||
if (n == 0) reverse(e::acc) ++ l
|
if (n == 0) e::l
|
||||||
else switch(l)
|
else switch(l)
|
||||||
[] => abort("insert_at overflow")
|
[] => abort("insert_at overflow")
|
||||||
h::t => insert_at_(n-1, e, t, h::acc)
|
h::t => h::insert_at_(n-1, e, t)
|
||||||
|
|
||||||
function insert_by(cmp : (('a, 'a) => bool), x : 'a, l : list('a)) : list('a) =
|
function insert_by(cmp : (('a, 'a) => bool), x : 'a, l : list('a)) : list('a) =
|
||||||
insert_by_(cmp, x, l, [])
|
|
||||||
private function insert_by_(cmp : (('a, 'a) => bool), x : 'a, l : list('a), acc : list('a)) : list('a) =
|
|
||||||
switch(l)
|
switch(l)
|
||||||
[] => reverse(x::acc)
|
[] => [x]
|
||||||
h::t =>
|
h::t =>
|
||||||
if(cmp(x, h)) // x < h
|
if(cmp(x, h)) // x < h
|
||||||
reverse(acc) ++ (x::l)
|
x::l
|
||||||
else
|
else
|
||||||
insert_by_(cmp, x, t, h::acc)
|
h::insert_by(cmp, x, t)
|
||||||
|
|
||||||
|
|
||||||
function foldr(cons : ('a, 'b) => 'b, nil : 'b, l : list('a)) : 'b = switch(l)
|
function foldr(cons : ('a, 'b) => 'b, nil : 'b, l : list('a)) : 'b = switch(l)
|
||||||
@ -102,43 +113,46 @@ namespace List =
|
|||||||
f(e)
|
f(e)
|
||||||
foreach(l', f)
|
foreach(l', f)
|
||||||
|
|
||||||
function reverse(l : list('a)) : list('a) = foldl((lst, el) => el :: lst, [], l)
|
function reverse(l : list('a)) : list('a) = reverse_(l, [])
|
||||||
|
private function reverse_(l : list('a), acc : list('a)) : list('a) = switch(l)
|
||||||
|
[] => acc
|
||||||
|
h::t => reverse_(t, h::acc)
|
||||||
|
|
||||||
function map(f : 'a => 'b, l : list('a)) : list('b) = map_(f, l, [])
|
function map(f : 'a => 'b, l : list('a)) : list('b) = switch(l)
|
||||||
private function map_(f : 'a => 'b, l : list('a), acc : list('b)) : list('b) = switch(l)
|
[] => []
|
||||||
[] => reverse(acc)
|
h::t => f(h)::map(f, t)
|
||||||
h::t => map_(f, t, f(h)::acc)
|
|
||||||
|
|
||||||
function flat_map(f : 'a => list('b), l : list('a)) : list('b) =
|
function flat_map(f : 'a => list('b), l : list('a)) : list('b) =
|
||||||
ListInternal.flat_map(f, l)
|
ListInternal.flat_map(f, l)
|
||||||
|
|
||||||
function filter(p : 'a => bool, l : list('a)) : list('a) = filter_(p, l, [])
|
function filter(p : 'a => bool, l : list('a)) : list('a) = switch(l)
|
||||||
private function filter_(p : 'a => bool, l : list('a), acc : list('a)) : list('a) = switch(l)
|
[] => []
|
||||||
[] => reverse(acc)
|
h::t =>
|
||||||
h::t => filter_(p, t, if(p(h)) h::acc else acc)
|
let rest = filter(p, t)
|
||||||
|
if(p(h)) h::rest else rest
|
||||||
|
|
||||||
/* Take `n` first elements */
|
/* Take up to `n` first elements */
|
||||||
function take(n : int, l : list('a)) : list('a) =
|
function take(n : int, l : list('a)) : list('a) =
|
||||||
if(n < 0) abort("Take negative number of elements") else take_(n, l, [])
|
if(n < 0) abort("Take negative number of elements") else take_(n, l)
|
||||||
private function take_(n : int, l : list('a), acc : list('a)) : list('a) =
|
private function take_(n : int, l : list('a)) : list('a) =
|
||||||
if(n == 0) reverse(acc)
|
if(n == 0) []
|
||||||
else switch(l)
|
|
||||||
[] => reverse(acc)
|
|
||||||
h::t => take_(n-1, t, h::acc)
|
|
||||||
|
|
||||||
/* Drop `n` first elements */
|
|
||||||
function drop(n : int, l : list('a)) : list('a) =
|
|
||||||
if(n < 0) abort("Drop negative number of elements")
|
|
||||||
elif (n == 0) l
|
|
||||||
else switch(l)
|
else switch(l)
|
||||||
[] => []
|
[] => []
|
||||||
h::t => drop(n-1, t)
|
h::t => h::take_(n-1, t)
|
||||||
|
|
||||||
|
/* Drop up to `n` first elements */
|
||||||
|
function drop(n : int, l : list('a)) : list('a) =
|
||||||
|
if(n < 0) abort("Drop negative number of elements") else drop_(n, l)
|
||||||
|
private function drop_(n : int, l : list('a)) : list('a) =
|
||||||
|
if (n == 0) l
|
||||||
|
else switch(l)
|
||||||
|
[] => []
|
||||||
|
h::t => drop_(n-1, t)
|
||||||
|
|
||||||
/* Get the longest prefix of a list in which every element matches predicate `p` */
|
/* Get the longest prefix of a list in which every element matches predicate `p` */
|
||||||
function take_while(p : 'a => bool, l : list('a)) : list('a) = take_while_(p, l, [])
|
function take_while(p : 'a => bool, l : list('a)) : list('a) = switch(l)
|
||||||
private function take_while_(p : 'a => bool, l : list('a), acc : list('a)) : list('a) = switch(l)
|
[] => []
|
||||||
[] => reverse(acc)
|
h::t => if(p(h)) h::take_while(p, t) else []
|
||||||
h::t => if(p(h)) take_while_(p, t, h::acc) else reverse(acc)
|
|
||||||
|
|
||||||
/* Drop elements from `l` until `p` holds */
|
/* Drop elements from `l` until `p` holds */
|
||||||
function drop_while(p : 'a => bool, l : list('a)) : list('a) = switch(l)
|
function drop_while(p : 'a => bool, l : list('a)) : list('a) = switch(l)
|
||||||
@ -146,17 +160,15 @@ namespace List =
|
|||||||
h::t => if(p(h)) drop_while(p, t) else l
|
h::t => if(p(h)) drop_while(p, t) else l
|
||||||
|
|
||||||
/* Splits list into two lists of elements that respectively match and don't match predicate `p` */
|
/* Splits list into two lists of elements that respectively match and don't match predicate `p` */
|
||||||
function partition(p : 'a => bool, l : list('a)) : (list('a) * list('a)) = partition_(p, l, [], [])
|
function partition(p : 'a => bool, l : list('a)) : (list('a) * list('a)) = switch(l)
|
||||||
private function partition_( p : 'a => bool
|
[] => ([], [])
|
||||||
, l : list('a)
|
h::t =>
|
||||||
, acc_t : list('a)
|
let (l, r) = partition(p, t)
|
||||||
, acc_f : list('a)
|
if(p(h)) (h::l, r) else (l, h::r)
|
||||||
) : (list('a) * list('a)) = switch(l)
|
|
||||||
[] => (reverse(acc_t), reverse(acc_f))
|
|
||||||
h::t => if(p(h)) partition_(p, t, h::acc_t, acc_f) else partition_(p, t, acc_t, h::acc_f)
|
|
||||||
|
|
||||||
|
function flatten(l : list(list('a))) : list('a) = switch(l)
|
||||||
function flatten(ll : list(list('a))) : list('a) = foldr((l1, l2) => l1 ++ l2, [], ll)
|
[] => []
|
||||||
|
h::t => h ++ flatten(t)
|
||||||
|
|
||||||
function all(p : 'a => bool, l : list('a)) : bool = switch(l)
|
function all(p : 'a => bool, l : list('a)) : bool = switch(l)
|
||||||
[] => true
|
[] => true
|
||||||
@ -172,25 +184,21 @@ namespace List =
|
|||||||
|
|
||||||
|
|
||||||
/* Zips two list by applying bimapping function on respective elements. Drops longer tail. */
|
/* Zips two list by applying bimapping function on respective elements. Drops longer tail. */
|
||||||
function zip_with(f : ('a, 'b) => 'c, l1 : list('a), l2 : list('b)) : list('c) = zip_with_(f, l1, l2, [])
|
private function zip_with( f : ('a, 'b) => 'c
|
||||||
private function zip_with_( f : ('a, 'b) => 'c
|
|
||||||
, l1 : list('a)
|
, l1 : list('a)
|
||||||
, l2 : list('b)
|
, l2 : list('b)
|
||||||
, acc : list('c)
|
|
||||||
) : list('c) = switch ((l1, l2))
|
) : list('c) = switch ((l1, l2))
|
||||||
(h1::t1, h2::t2) => zip_with_(f, t1, t2, f(h1, h2)::acc)
|
(h1::t1, h2::t2) => f(h1, h2)::zip_with(f, t1, t2)
|
||||||
_ => reverse(acc)
|
_ => []
|
||||||
|
|
||||||
/* Zips two lists into list of pairs. Drops longer tail. */
|
/* Zips two lists into list of pairs. Drops longer tail. */
|
||||||
function zip(l1 : list('a), l2 : list('b)) : list('a * 'b) = zip_with((a, b) => (a, b), l1, l2)
|
function zip(l1 : list('a), l2 : list('b)) : list('a * 'b) = zip_with((a, b) => (a, b), l1, l2)
|
||||||
|
|
||||||
function unzip(l : list('a * 'b)) : list('a) * list('b) = unzip_(l, [], [])
|
function unzip(l : list('a * 'b)) : (list('a) * list('b)) = switch(l)
|
||||||
private function unzip_( l : list('a * 'b)
|
[] => ([], [])
|
||||||
, acc_l : list('a)
|
(h1, h2)::t =>
|
||||||
, acc_r : list('b)
|
let (t1, t2) = unzip(t)
|
||||||
) : (list('a) * list('b)) = switch(l)
|
(h1::t1, h2::t2)
|
||||||
[] => (reverse(acc_l), reverse(acc_r))
|
|
||||||
(left, right)::t => unzip_(t, left::acc_l, right::acc_r)
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: Improve?
|
// TODO: Improve?
|
||||||
@ -200,15 +208,14 @@ namespace List =
|
|||||||
(lesser, bigger) => sort(lesser_cmp, lesser) ++ h::sort(lesser_cmp, bigger)
|
(lesser, bigger) => sort(lesser_cmp, lesser) ++ h::sort(lesser_cmp, bigger)
|
||||||
|
|
||||||
|
|
||||||
function intersperse(delim : 'a, l : list('a)) : list('a) = intersperse_(delim, l, [])
|
function intersperse(delim : 'a, l : list('a)) : list('a) = switch(l)
|
||||||
private function intersperse_(delim : 'a, l : list('a), acc : list('a)) : list('a) = switch(l)
|
[] => []
|
||||||
[] => reverse(acc)
|
[e] => [e]
|
||||||
[e] => reverse(e::acc)
|
h::t => h::delim::intersperse(delim, t)
|
||||||
h::t => intersperse_(delim, t, delim::h::acc)
|
|
||||||
|
|
||||||
|
|
||||||
function enumerate(l : list('a)) : list(int * 'a) = enumerate_(l, 0, [])
|
function enumerate(l : list('a)) : list(int * 'a) = enumerate_(l, 0)
|
||||||
private function enumerate_(l : list('a), n : int, acc : list(int * 'a)) : list(int * 'a) = switch(l)
|
private function enumerate_(l : list('a), n : int) : list(int * 'a) = switch(l)
|
||||||
[] => reverse(acc)
|
[] => []
|
||||||
h::t => enumerate_(t, n + 1, (n, h)::acc)
|
h::t => (n, h)::enumerate_(t, n + 1)
|
||||||
|
|
||||||
|
@ -53,17 +53,17 @@ namespace Option =
|
|||||||
None => []
|
None => []
|
||||||
Some(x) => [x]
|
Some(x) => [x]
|
||||||
|
|
||||||
function filter_options(l : list(option('a))) : list('a) = filter_options_(l, [])
|
function filter_options(l : list(option('a))) : list('a) = switch(l)
|
||||||
private function filter_options_(l : list (option('a)), acc : list('a)) : list('a) = switch(l)
|
[] => []
|
||||||
[] => List.reverse(acc)
|
None::t => filter_options(t)
|
||||||
None::t => filter_options_(t, acc)
|
Some(x)::t => x::filter_options(t)
|
||||||
Some(x)::t => filter_options_(t, x::acc)
|
|
||||||
|
|
||||||
function seq_options(l : list (option('a))) : option (list('a)) = seq_options_(l, [])
|
function seq_options(l : list (option('a))) : option (list('a)) = switch(l)
|
||||||
private function seq_options_(l : list (option('a)), acc : list('a)) : option(list('a)) = switch(l)
|
[] => Some([])
|
||||||
[] => Some(List.reverse(acc))
|
None::_ => None
|
||||||
None::t => None
|
Some(x)::t => switch(seq_options(t))
|
||||||
Some(x)::t => seq_options_(t, x::acc)
|
None => None
|
||||||
|
Some(st) => Some(x::st)
|
||||||
|
|
||||||
|
|
||||||
function choose(o1 : option('a), o2 : option('a)) : option('a) =
|
function choose(o1 : option('a), o2 : option('a)) : option('a) =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user