package alba
Source file list.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167include Stdlib.List include Module_types type 'a t = 'a list let return (a:'a): 'a t = [a] let rec (>>=) (l:'a t) (f:'a -> 'b t): 'b t = match l with | [] -> [] | hd :: tl -> f hd @ (tl >>= f) let (>=>) (f:'a -> 'b t) (g:'b -> 'c t) (a:'a): 'c t = f a >>= g let (<*>) (flst: ('a -> 'b) t) (lst:'a t): 'b t = flst >>= fun f -> map f lst let join = concat let find (p:'a -> bool) (l:'a t): 'a option = try Some (find p l) with Not_found -> None let nth (i: int) (lst: 'a t): 'a option = nth_opt lst i let nth_strict (i: int) (lst: 'a t): 'a = match nth i lst with | None -> assert false (* Illegal call! *) | Some e -> e let split_head_tail (lst: 'a t): 'a * 'a t = assert (lst <> []); match lst with | [] -> assert false (* Illegal call! *) | hd :: tl -> hd, tl let head_strict (lst: 'a t): 'a = assert (lst <> []); fst (split_head_tail lst) let tail_strict (lst: 'a t): 'a t = assert (lst <> []); snd (split_head_tail lst) let map_and_filter (f:'a -> 'b option) (l:'a list): 'b list = let rec map = function | [] -> [] | hd :: tl -> match f hd with | None -> map tl | Some b -> b :: map tl in map l let split_at (p:'a -> bool) (l: 'a t): 'a t * 'a t = let rec split prefix rest = match rest with | [] -> rev prefix, rest | hd :: tl -> if p hd then rev prefix, rest else split (hd :: prefix) tl in split [] l let transpose (row_list: 'a list list): 'a list list = assert (row_list <> []); let first_column row_list = (* Extract the first column of [row_list]. *) fold_right (fun row (column, row_list)-> match row with | [] -> assert false | el :: rest_row -> el :: column, rest_row :: row_list ) row_list ([], []) in let rec get_columns columns row_list = match row_list with | [] -> assert false (* No rows is not allowed. *) | [] :: _ -> columns | (_ :: _) :: _ -> let column, row_list = first_column row_list in get_columns (column :: columns) row_list in rev (get_columns [] row_list) module Monadic (M: MONAD) = struct let foldi_left (f:int -> 'a -> 'b -> 'b M.t) (l:'a t) (start:'b) : 'b M.t = let rec foldi i l start = match l with | [] -> M.return start | hd :: tl -> M.(f i hd start >>= foldi (i+1) tl) in foldi 0 l start let fold_left (f:'a -> 'b -> 'b M.t) (l:'a t) (start:'b): 'b M.t = foldi_left (fun _ -> f) l start let fold_right (f:'a -> 'b -> 'b M.t) (l:'a t) (start:'b): 'b M.t = fold_left f (rev l) start end (* Unit Tests *) let%test _ = transpose [ [1] ] = [ [1] ] let%test _ = transpose [ [1;2;3] ] = [ [1]; [2]; [3] ] let%test _ = transpose [ [1;2;3]; [4;5;6] ] = [ [1;4]; [2;5]; [3;6] ]