Useful generic functions are usually the result of composing useful generic functions; the fact that these are easy to write is, however, not an excuse for not having them in a rich prelude. Given a total function for splitting a list at a given point:
let rec split_at n = function | [] -> [], [] | l when n == 0 -> [], l | x :: xs -> let l, r = split_at (pred n) xs in x :: l, r
and the anamorphism on lists, the basic functional iteration scheme giving the list of results:
let rec unfold f e = match f e with | None -> [] | Some (x, e') -> x :: unfold f e'
then splitting a list into chunks just requires some assembly:
let chunks n = unfold (fun l -> match split_at n l with [], [] -> None | p -> Some p)
As another example, suppose we need a Procrustean function fit
that truncates a list or pads it with a value to a given length. Given an way to build an infinite list:
let all x = let rec l = x :: l in l
the desired function is just:
let fit n e l = fst (split_at n (l @ all e))
The only good thing about the paucity of Pervasives
is that it forces one to practice often this kind of finger exercises. At least they are pretty.
1 comment:
Of course, take == fst % split_at, and similarly for drop == snd % split_at.
Post a Comment