Your function accepts an integer n, and takes n elements from a list list, which is the list which contains the n first elements of list.
So your signature is likely to be:
int -> 'a list -> 'a list = <fun>
You probably already can guess that the function is going to be defined recursively, so you can already write the definition of your function like this:
let rec take n list = ...
You have to build a list, but let's first consider three major classes of values for n:
- n = 0 : just return an empty list
- n > 0 : take one element and recurse with n - 1
- n < 0 : The negative case is easy to miss, but if you are not cautious, you can easily enter an infinite recursion at runtime with invalid inputs. Here, fortunately, we are going to use an exception and make things terminate down the recursive chain (that's what happens in moldbino's answer, for example), but other functions might not behave as nicely.
Some implementations of
take
, when given a negative numbers, try to be useful and takes n elements from the end of the list.
Here we will simply treat any n that is not strictly positive as-if if was null.
Null or negative N
When we take zero elements from a list, that means that we return the empty list:
let rec take n list =
if n > 0
then ...
else [];;
Positive N
Now, we consider the case where we take n > 0 elements from a list.
Following the recursive definition of lists, we have to consider each possible kind of lists, namely the empty list and non-empty lists.
let rec take n list =
if n > 0
then
match list with
| [] -> ...
| x :: xs -> ...
else [];;
What happens when we want to take n > 0 elements from an empty list?
We fail.
let rec take n list =
if n > 0 then
match list with
| [] -> failwith "Not enough elements in list"
| x :: xs -> ...
else [];;
Now, the general case of recursion. We have a non-empty list, and n > 0, so we know that we can take at least one element from the list.
This value is x
, which forms the head of the list we want to return. The tail of the list is the one made of the n-1 elements of xs, which is easily computed by take
itself:
let rec take n list =
if n > 0 then
match list with
| [] -> failwith "Not enough elements in list"
| x :: xs -> x :: (take (n - 1) xs)
else [];;