ligo/vendors/ligo-utils/simple-utils/x_list.ml

210 lines
4.9 KiB
OCaml

include List
let rec remove n = function
| [] -> raise (Failure "List.remove")
| _ :: tl when n = 0 -> tl
| hd :: tl -> hd :: remove (n - 1) tl
let rec take n = function
| [] -> []
| _ when n = 0 -> []
| hd :: tl -> hd :: take (n - 1) tl
let map ?(acc = []) f lst =
let rec aux acc f = function
| [] -> acc
| hd :: tl -> aux (f hd :: acc) f tl
in
aux acc f (List.rev lst)
let fold_map_right : type acc ele ret . (acc -> ele -> (acc * ret)) -> acc -> ele list -> ret list =
fun f acc lst ->
let rec aux (acc , prev) f = function
| [] -> (acc , prev)
| hd :: tl ->
let (acc' , hd') = f acc hd in
aux (acc' , hd' :: prev) f tl
in
snd @@ aux (acc , []) f (List.rev lst)
let fold_map_acc : type acc ele ret . (acc -> ele -> (acc * ret)) -> acc -> ele list -> acc * ret list =
fun f acc lst ->
let rec aux (acc , prev) f = function
| [] -> (acc , prev)
| hd :: tl ->
let (acc' , hd') = f acc hd in
aux (acc' , hd' :: prev) f tl
in
let (acc, lst) = aux (acc , []) f lst in
(acc, List.rev lst)
let fold_map : type acc ele ret . (acc -> ele -> (acc * ret)) -> acc -> ele list -> ret list =
fun f acc lst ->
snd (fold_map_acc f acc lst)
let fold_right' f init lst = List.fold_left f init (List.rev lst)
(* breaking a dependency cycle with X_option *)
let unopt ~default x = match x with
| None -> default
| Some x -> x
let rec remove_element ?compare:cmp x lst =
let compare = unopt ~default:compare cmp in
match lst with
| [] -> raise (Failure "X_list.remove_element")
| hd :: tl when compare x hd = 0 -> tl
| hd :: tl -> hd :: remove_element ~compare x tl
let filter_map f =
let rec aux acc lst = match lst with
| [] -> List.rev acc
| hd :: tl -> aux (
match f hd with
| Some x -> x :: acc
| None -> acc
) tl
in
aux []
let cons_iter = fun fhd ftl lst ->
match lst with
| [] -> ()
| hd :: tl -> fhd hd ; List.iter ftl tl
let range n =
let rec aux acc n =
if n = 0
then acc
else aux ((n-1) :: acc) (n-1)
in
aux [] n
let find_map f lst =
let rec aux = function
| [] -> None
| hd::tl -> (
match f hd with
| Some _ as s -> s
| None -> aux tl
)
in
aux lst
let find_index f lst =
let rec aux n = function
| [] -> raise (Failure "find_index")
| hd :: _ when f hd -> n
| _ :: tl -> aux (n + 1) tl in
aux 0 lst
let find_full f lst =
let rec aux n = function
| [] -> raise (Failure "find_index")
| hd :: _ when f hd -> (hd, n)
| _ :: tl -> aux (n + 1) tl in
aux 0 lst
let assoc_i ~compare x lst =
let rec aux n = function
| [] -> raise (Failure "List:assoc_i")
| (x', y) :: _ when compare x x' = 0 -> (y, n)
| _ :: tl -> aux (n + 1) tl
in
aux 0 lst
let rec from n lst =
if n = 0
then lst
else from (n - 1) (tl lst)
let until n lst =
let rec aux acc n lst =
if n = 0
then acc
else aux ((hd lst) :: acc) (n - 1) (tl lst)
in
rev (aux [] n lst)
let uncons_opt = function
| [] -> None
| hd :: tl -> Some (hd, tl)
let rev_uncons_opt = function
| [] -> None
| lst ->
let r = rev lst in
let last = hd r in
let hds = rev @@ tl r in
Some (hds , last)
let hds lst = match rev_uncons_opt lst with
| None -> failwith "toto"
| Some (hds , _) -> hds
let to_pair = function
| [a ; b] -> Some (a , b)
| _ -> None
let to_singleton = function
| [a] -> Some a
| _ -> None
(** overriding stdlib List functions with optional compare/eq
arguments *)
let rec mem ?compare:cmp x =
let compare = unopt ~default:compare cmp in
function
| [] -> false
| a::l -> compare a x = 0 || mem ~compare x l
let rec memq ?eq:eq x =
let eq = unopt ~default:(=) eq in
function
| [] -> false
| a::l -> eq a x || memq ~eq x l
let rec assoc ?compare:cmp x =
let compare = unopt ~default:compare cmp in
function
[] -> raise Not_found
| (a,b)::l -> if compare a x = 0 then b else assoc ~compare x l
let rec assoc_opt ?compare:cmp x =
let compare = unopt ~default:compare cmp in
function
[] -> None
| (a,b)::l -> if compare a x = 0 then Some b else assoc_opt ~compare x l
module Ne = struct
type 'a t = 'a * 'a list
let of_list lst = List.hd lst, List.tl lst
let to_list (hd, tl : _ t) = hd :: tl
let singleton hd : 'a t = hd , []
let hd : 'a t -> 'a = fst
let cons : 'a -> 'a t -> 'a t = fun hd' (hd , tl) -> hd' , hd :: tl
let iter f (hd, tl : _ t) = f hd ; List.iter f tl
let map f (hd, tl : _ t) = f hd, List.map f tl
let hd_map : _ -> 'a t -> 'a t = fun f (hd , tl) -> (f hd , tl)
let mapi f (hd, tl : _ t) =
let lst = List.mapi f (hd::tl) in
of_list lst
let concat (hd, tl : _ t) = hd @ List.concat tl
let rev (hd, tl : _ t) =
match tl with
| [] -> (hd, [])
| lst ->
let r = List.rev lst in
(List.hd r, List.tl r @ [hd])
let find_map = fun f (hd , tl : _ t) ->
match f hd with
| Some x -> Some x
| None -> find_map f tl
end