Haskellのリスト操作をOCamlに移植(1)

30分プログラム、その342。たまにはProject Euler以外も。
Haskellの関数、特にPreludeにあるようなやつは実に考えられている。例えば、foldl1あたりは簡単に書けるのに、かなりいろんなところで使えて便利だったりする。
というわけで、このあたりの関数をOCamlに移植してみる。とりあえずリスト関係の関数から。いちおうユニットテストも書いておいた。

使い方

# last [1;2];;
- : int = 2p
# sum [1;2;3];;
- : int = 6

ソースコード

let (@@) f g = f g
let ($) f g x = f (g x)

let rec last =
  function
      [] ->
	invalid_arg "HList.last"
    | [x] -> 
	x
    | x::xs -> 
	last xs

let init xs =
  let rec init' ys =
    function
	[]  ->
	  invalid_arg "HList.init"
      |	[_] ->
	  List.rev ys
      | x::xs ->
	  init' (x::ys) xs in
    init' [] xs

let null =
  function
      [] -> 
	true
    | _ -> 
	false

let fold_left1 f (x::xs) =
  List.fold_left f x xs

let rec fold_right1 f =
  function
      []    ->
	invalid_arg "HList.fold_right1"
    | [x]   ->
	x
    | x::xs ->
	f x (fold_right1 f xs)

let conj =
  List.fold_left (&&) true

let disj =
  List.fold_left (||) false

let sum =
  List.fold_left (+) 0

let product =
  List.fold_left ( * ) 1

let concat_map f xs =
  List.fold_right ((@) $ f) xs []