Вы не можете избежать копирования первой половины списка. Список является неизменным, поэтому единственный способ получить новый список - это скопировать элементы из исходного списка.
Вторая половина списка не требует копирования, потому что хвост списка - это список .
Для этого нет встроенной функции (в любом случае, в стандартной библиотеке OCaml), поэтому я бы посоветовал вам написать свою собственную.
Это очень похоже на то, что произойдет домашнее задание, поэтому я просто скажу, что способ написания большинства функций списка на функциональном языке - спросить себя, как можно использовать функцию, которая работает для меньшего ввода (как правило, хвоста списка) для вычисления значение для вашего исходного ввода.
В вашем случае у вас есть что-то вроде этого:
let rec split_at_point l n =
if n = 0 then
(* Answer is obvious *)
else
match l with
| [] -> (* Answer is obvious *)
| head :: tail ->
(* Call split_at_point on the tail and
* construct your answer
*)