In Haskell, there is a function "take n list" which returns the first n elements from a list. For example "sum (take 3 xs)" sums up the first three elements in the list xs. Does F# have an equivalent? I expected it to be one of the List-functions, but I can't spot anything that seems to match.
4 Answers
To clarify a few things, the difference between Seq.take
and Seq.truncate
(as pointed out by @sepp2k) is that the second one will give you a sequence that returns at most the number of elements you specified (but if the length of the sequence is less, it will give you less elements).
The sequence generated Seq.take
function will throw an exception if you try to access an element beyond the length of the original list (Note that the Seq.take
function doesn't throw the exception immediately, because the result is lazily generated sequence).
Also, you don't need to convert the list to a sequence explicitly. Under the cover, list<'a>
is a .NET class that inherits from the seq<'a>
type, which is an interface. The type seq<'a>
is actually just a type alias for IEnumerable<'a>
, so it is implemented by all other collections (including arrays, mutable lists, etc.). The following code will work fine:
let list = [ 1 .. 10 ]
let res = list |> Seq.take 5
However, if you want to get a result of type list<int>
you'll need to convert sequence back to a list (because a list is more specific type than a sequence):
let resList = res |> List.ofSeq
I'm not sure why F# libraries don't provide List.take
or List.truncate
. I guess the goal was to avoid reimplementing the whole set of functions for all types of collections, so those where the implementation for sequences is good enough when working with a more specific collection type are available only in the Seq
module (but that's only my guess...)

- 240,744
- 19
- 378
- 553
-
@McMuttons: Thanks! I wasn't sure whether I should post it or not, because most of the things were already mentioned in the comments.. So, I'm glad it is usedul! – Tomas Petricek Apr 13 '10 at 22:11
-
It looks like [`List.truncate`](https://fsharp.github.io/fsharp-core-docs/reference/fsharp-collections-listmodule.html#truncate) and [`List.take`](https://fsharp.github.io/fsharp-core-docs/reference/fsharp-collections-listmodule.html#take) are now in the core F# libraries – Jonathan Tyson Mar 19 '21 at 14:15
Yeah, it's called Seq.take
. Usage seems to be identical to Haskell's: Seq.take
count source. To use it on a list, use (Update: Apparently from the comments, this isn't necessary.)List.toSeq
first.

- 14,472
- 3
- 50
- 54
-
-
18
-
2Since list inherits from IEnumerable, you don't have to convert it to a sequence first from what I can see. Using Seq.take on a list worked fine. – McMuttons Apr 13 '10 at 20:23
-
@sepp2k: Yeah, you're right. I didn't know that. The documentation I linked explains the difference, which is pretty subtle in my opinion. – Joren Apr 13 '10 at 20:24
-
1@McMuttons: Fair enough. I did expect Seq operations to work on a list, but I have almost no experience with F#, so wasn't sure. I mentioned the conversion function just in case. – Joren Apr 13 '10 at 20:27
-
Yeah, good function to know about either way. Appreciate the help. And damnit, I accidentally removed my +1 on your answer, but it doesn't seem to let me add it again unless you edit it in some way. – McMuttons Apr 13 '10 at 20:29
Seq.take works, as others already have stated, but all Seq operations on a list come at a cost. In the case of Seq.take, it's not surprising, as the list has to be copied.
It's more noteworthy that, for example, Seq.concat on a list takes a lot more time than List.concat. I suppose that implies that you don't just access the list as a seq when you call a Seq.xxx function, but that the list in copied/converted to a Seq behind the scenes as well.
edit: The reason I drew the conclusion above, was this bench using F# interactive:
#time "on";;
let lists = [for i in 0..5000000 -> [i..i+1]];;
Seq.length (Seq.concat lists);;
List.length (List.concat lists);;
On my machine, the List.length
version takes about 1.9 secs, whereas the Seq.length
version takes about 3.8 secs (shortest time of a few repeated tests of the length lines only, excluding the list generation line).

- 4,927
- 4
- 34
- 42
-
4I don't think that this is correct. `list<'t>` implements the `seq<'t>` interface so there is no conversion necessary, nor is there any reason to expect a copy to be made. Also, `Seq.take` works lazily, whereas `List.take` couldn't, so on a long list, the sequence operations will almost certainly be quicker if only the front of the resulting sequence is needed. However, it may be true that implementing a `List.take` function via pattern matching would perform better than the `Seq.take` implementation which enumerates the list if you want to eagerly access all elements of the resulting list. – kvb Sep 14 '11 at 14:00
-
2My conclusion about conversions taking place was probably wrong, but something's going on and it takes extra time. I edited my post and added some timings. – John Reynolds Sep 25 '11 at 10:44
Elaborating on @Jonathan Tyson comment
List.take is now part of the standard F# library and it is recommended to use that instead of the Seq.Take
The following should work
List.take <count>
Also, see this answer to understand the difference between take and truncate

- 323
- 1
- 5