(* Exercise: mystery operator 1 *)
let ( $ ) f x = f x;;
(* 使得函数的连续调用具有一部分右结合的特质 square $ 2 + 2 与 square 2 + 2 的运行结果分别是 16 和 6 *)
(* Exercise: repeat *)
let rec repeat f n x =
match n with
| 0 -> x
| _ -> repeat f (n - 1) (f x);;
(* Exercise: product *)
let product = function
| [] -> 1
| h :: t -> List.fold_left ( * ) h t;;
(* Exercise: terse product *)
let terse_product = List.fold_left ( * ) 1;; (* Orz 我宣布 Ocaml 是世界上最美的语言 *)
(* Exercise: sum_cube_odd *)
let rec ( -- ) i j = if i > j then [] else i :: (i + 1 -- j);;
let odd x = if x mod 2 = 1 then true else false;;
let cube x = x * x * x;;
let sum = List.fold_left ( + ) 0;;
let sum_cube_add n = sum @@ List.map cube @@ List.filter odd @@ ( -- ) 0 n;;
(* Exercise: sum_cube_odd pipeline *)
let sum_cube_odd_pipe n = ( -- ) 0 n |> List.filter odd |> List.map cube |> List.fold_left ( + ) 0;;
(* Exercise: exists *)
let rec exists_rec f = function
| [] -> false
| h :: t -> if f h then true else (exists_rec f t);;
let exists_fold f = List.fold_left (fun x y -> x || f y) false;;
let exists_libs f l = List.fold_left ( || ) false @@ List.map f l;;
(* Exercise: library uncarried *)
let uncarried_append (l1, l2) = List.append l1 l2;;
(* Exercise: map composition *)
let map_composition = fun f g l -> List.map (fun x -> f (g x)) l;; (* f @@ g 好像无法通过类型推断 solution 应该是错了 具体解释等我学完解释器 :) *)
let map_composition_test = map_composition (fun x -> x + 1) (fun x -> x * x) [1; 2; 3; 4; 5];;
(* Exercise: more list fun *)
let greater_then_3 = List.filter (fun x -> x > 3);;
let add_1 = List.map (fun x -> x +. 1.0);;
let gather_sentence strs sep = List.fold_left (fun x y -> if x = "" then y else x ^ sep ^ y) "" strs;;
(* Exercise: association list keys *)
let keys : ('a * 'b) list -> 'a list = fun lst -> List.map (fun (x, y) -> x) lst |> List.sort_uniq compare;;
(* Exercise: valid matrix *)
let is_valid_matrix = function
| [] -> false
| m -> List.map List.length m |> List.sort_uniq compare |> List.length = 1;;
(* Exercise: row vector add *)
let add_row_vectors v1 v2 = List.map2 ( + ) v1 v2;;
(* Exercise: matrix add *)
let add_matrices m1 m2 = List.map2 add_row_vectors m1 m2;;
(* Exercise: matrix multiply *)
let transpose m = List.map (fun i -> List.map (fun x -> List.nth x i) m) (0 -- (List.length (List.hd m) - 1));;
let mul_row_vectors v1 v2 = List.fold_left ( + ) 0 @@ List.map2 ( * ) v1 v2;;
let multiply_matrices m1 m2 = List.map (fun x -> List.map (fun y -> mul_row_vectors x y) (transpose m2)) m1;;