Testcases for NUnit 3 tests in F# - f#

I am trying to set up a test suite for an F# project using NUnit.
It seems that especially when testing things like parsers and type checkers one typically has a list of valid input data and a list of invalid data.
The tests itself are practically identical, so I am looking for a clever way to avoid writing a test function for each and every data item and instead seperate the test function from the data.
Apparently, there seems to be something called test cases for that but I am having a hard time to find comprehensive documentation for the usage of NUnit 3 with F# in general and specifically a best practice example for my scenario.
Any pointers and hints are greately appreaciated!

This is an updated answer for NUnit 3.x since my original answer showed a NUnit 2.x example.
The examples below are not meant to be comprehensive, but enough to get you over the threshold and up an running. The things of note are that the test functions are written using argument list instead of currying. Also there are several ways to generate test data using NUnit 3.x attributes, e.g. Pairwise, but sadly none of the attributes available know how to generate test data for discriminated unions.
Also FSUnit is not needed and I didn't try to make it work as the difference between NUnint 2.x and 3.x are so dramatic that I was happy just to get the following examples working. Maybe in the future I will update this answer.
namespace NUnit3Demo
open NUnit.Framework
module MyTest =
// ----------------------------------------------------------------------
[<Pairwise>]
let pairWiseTest([<Values("a", "b", "c")>] (a : string), [<Values("+", "-")>] (b :string), [<Values("x", "y")>] (c : string))
= printfn "%A %A %A" a b c
// ----------------------------------------------------------------------
let divideCases1 =
[
12, 3, 4
12, 2, 6
12, 4, 3
] |> List.map (fun (q, n, d) -> TestCaseData(q,n,d))
[<TestCaseSource("divideCases1")>]
let caseSourceTest1(q:int, n:int, d:int) =
Assert.AreEqual( q, n / d )
// ----------------------------------------------------------------------
let divideCases2 =
seq {
yield (12, 3, 4)
yield (12, 2, 6)
yield (12, 4, 3)
}
[<TestCaseSource("divideCases2")>]
let caseSourceTest2(q:int, n:int, d:int) =
Assert.AreEqual( q, n / d )
// ----------------------------------------------------------------------
[<TestCase(12,3,4)>]
[<TestCase(12,2,6)>]
[<TestCase(12,4,3)>]
let testCaseTest(q:int, n:int, d:int) =
Assert.AreEqual( q, n / d )
// ----------------------------------------------------------------------
let evenNumbers : int [] = [| 2; 4; 6; 8 |]
[<TestCaseSource("evenNumbers")>]
let caseSourceTest3 (num : int) =
Assert.IsTrue(num % 2 = 0)
Leaving Original Answer since it was noted in other answer by OP.
The following example was written 3 years ago using NUnit 2.x so it is a bit dated but should give you an ideal.
You create an array of the test data, then index into the array to pull out the test values and expected results. The nice thing about this is that you don't wind up writing lots of individual test for a function.
This comes from a project some of us did years ago.
open NUnit.Framework
open FsUnit
let private filterValues : (int list * int list)[] = [|
(
// idx 0
// lib.filter.001
[],
[]
);
(
// idx 1
// lib.filter.002
[-2],
[-2]
);
(
// idx 2
// lib.filter.003
[-1],
[]
);
(
// idx 3
// lib.filter.004
[0],
[0]
);
(
// idx 4
// lib.filter.005
[1],
[]
);
(
// idx 5
// lib.filter.006
[1; 2],
[2]
);
(
// idx 6
// lib.filter.007
[1; 3],
[]
);
(
// idx 7
// lib.filter.008
[2; 3],
[2]
);
(
// idx 8
// lib.filter.009
[1; 2; 3],
[2]
);
(
// idx 9
// lib.filter.010
[2; 3; 4],
[2; 4]
);
|]
[<Test>]
[<TestCase(0, TestName = "lib.filter.01")>]
[<TestCase(1, TestName = "lib.filter.02")>]
[<TestCase(2, TestName = "lib.filter.03")>]
[<TestCase(3, TestName = "lib.filter.04")>]
[<TestCase(4, TestName = "lib.filter.05")>]
[<TestCase(5, TestName = "lib.filter.06")>]
[<TestCase(6, TestName = "lib.filter.07")>]
[<TestCase(7, TestName = "lib.filter.08")>]
[<TestCase(8, TestName = "lib.filter.09")>]
[<TestCase(9, TestName = "lib.filter.10")>]
let ``List filter`` idx =
let (list, _) = filterValues.[idx]
let (_, result) = filterValues.[idx]
List.filter (fun x -> x % 2 = 0) list
|> should equal result
filter (fun x -> x % 2 = 0) list
|> should equal result
IIRC the problem with using NUnit with F# is to remember to use <> in the right location.

In NUnit3 there is TestCaseSource and TestCaseData and for the best practices part I added FsUnit:
namespace NUnit3Demo
open NUnit.Framework
open FsUnit
[<TestFixture>]
module MyTest =
let methodToBeTested s =
if String.length s > 3 then failwith "Something's wrong"
else String.length s
let validData =
[
TestCaseData(" ").Returns(3)
TestCaseData("").Returns(0)
TestCaseData("a").Returns(1)
]
let invalidData =
[
" "
"abcd"
"whatever"
]
let otherInvalidData =
[
"just"
"because"
]
[<TestCaseSource("invalidData");
TestCaseSource("otherInvalidData")>]
let ``More than 3 characters throws`` s =
(fun () -> methodToBeTested s |> ignore)
|> should throw typeof<System.Exception>
[<TestCaseSource("validData")>]
let ``Less than 4 characters returns length`` s =
methodToBeTested s
Note that TestCaseData can take and return arbitrary objects (obviously they should match the test signatures). Also, the data can be written even nicer:
let validData =
[
" ", 3
"", 0
"a", 1
] |> List.map (fun (d, r) -> TestCaseData(d).Returns r)

By the end of the day, I realised I should not have used an array in the first place!
I finally understood how the TestCase mechanism is supposed to work:
it simply passes the annotation's contents as a parameter to a function that now is not unit->unit anymore but (in my case) string->unit. Thus all my data items are now pasted into individual TestCase annotations, and the array is gone. Surely this might look a bit odd, to have TestCase annotations whose contents span many lines of code but the array was not beautiful either, so be it.
Unfortunately, my solution is not universally applicable, e.g. would not work for Guy Coder's code above. The reason is indicated here: https://stackoverflow.com/a/28015585/2289899 where they say:
CLI has a restriction regarding kinds of attribute parameters:
primitive: bool, int, float, etc
enums
strings
type references: System.Type
'kinda objects': boxed (if needed) representation of types from above
one dimensional array of one of types from above (ie. no nested arrays allowed)
So we can conclude at this point that you can not use tuple as an
attribute parameter's type.

Related

Example of the difference between List.fold and List.foldBack

My understanding of the difference between List.fold and List.foldBack is that foldBack iterates over its list in a reverse order. Both functions accumulate a result from the items in the list.
I'm having trouble coming up with a good example where it is preferable to foldBack over a list. In the examples I have come up with, the results are the same for both fold and foldBack, if the function logic does the same thing.
[<Fact>]
let ``List.foldBack accumulating a value from the right to the left``() =
let list = [1..5]
let fFoldBack x acc =
acc - x
let fFold acc x =
acc - x
let foldBackResult = List.foldBack fFoldBack list 0
let foldResult = List.fold fFold 0 list
Assert.Equal( -15, foldBackResult ) // 0 - 5 - 4 - 3 - 2 - 1
Assert.Equal( -15, foldResult ) // 0 - 1 - 2 - 3 - 4 - 5
You don't see a difference in your example because you chose a function such that for any x1 and x2:
(acc - x1) - x2 = (acc - x2) - x1
So it doesn't matter in what order you go through the list, you will get the same result.
List construction is an example of function for which it is not the case:
x1 :: (x2 :: acc) <> x2 :: (x1 :: acc)
So the following will yield different results:
List.fold (fun acc x -> x :: acc) [] [1; 2; 3; 4; 5]
// val it : int list = [5; 4; 3; 2; 1]
List.foldBack (fun x acc -> x :: acc) [1; 2; 3; 4; 5] [];;
// val it : int list = [1; 2; 3; 4; 5]
List.fold starts with an empty result list and goes forward through the input, adding each element to the front of the result list; therefore the final result is in the reverse order.
List.foldBack, on the other hand, goes backward through the input; so each element newly added to the front of the result list was itself to the front in the original list. So the final result is the same list as the original.
Tarmil's answer has already demonstrated the difference between the two in a good, concise manner. I'm going to give an example that uses a somewhat more complex data type. (Actually, if you ignore the naming then my example is a linked list, but you can imagine how it could be expanded to something much more complex.)
The purpose of fold vs. foldBack isn't necessarily obvious when you are computing a scalar value, but when you start using it to build data structures, it becomes clear that most such structures must be built in a particular direction. This is especially true if you use immutable data structures, since you don't have the option of constructing a node and then updating it to point to another node.
In this example, I've defined a structure for a trivial programming language that does nothing but print numbers. It recognizes two instructions, Print and End. Each print instruction stores a pointer to the next instruction. Thus, a program consists of a chain of instructions, each pointing to the next. (The reason I've used this particular example is because, by executing the program, you demonstrate its structure.)
The program uses three different methods of constructing the program from a list of integers. The first, make_list_printer, is defined recursively with no fold, to demonstrate what we're trying to achieve. The second, make_list_printer_foldBack, uses foldBack to achieve the same result. The third, make_list_printer_fold, uses fold to demonstrate how it produces the wrong result.
I've mostly coded in OCaml, not F#, so I apologize if some of the coding conventions used below aren't really considered proper style in F#. I did test it in the F# interpreter, though, and it works.
(* Data structure of our mini-language. *)
type prog =
| End
| Print of int * prog
(* Builds a program recursively. *)
let rec make_list_printer = function
| [] -> End
| i :: program -> Print (i, make_list_printer program)
(* Builds a program using foldBack. *)
let make_list_printer_foldBack ints =
List.foldBack (fun i p -> Print (i, p)) ints End
(* Builds a program in the wrong direction. *)
let make_list_printer_fold ints =
List.fold (fun p i -> Print (i, p)) End ints
(* The interpreter for our mini-language. *)
let rec run_list_printer = function
| End ->
printfn ""
| Print (i, program) ->
printf "%d " i;
run_list_printer program
(* Build and run three different programs based on the same list of numbers. *)
let () =
let base_list = [1; 2; 3; 4; 5] in
let a = make_list_printer base_list in
let b = make_list_printer_foldBack base_list in
let c = make_list_printer_fold base_list in
run_list_printer a;
run_list_printer b;
run_list_printer c
The output that I get when I run this is:
1 2 3 4 5
1 2 3 4 5
5 4 3 2 1

Modifying RX Computational Expression Builder to hold previous values

I'm using a slightly modified version of the RX builder presented here:
http://mnajder.blogspot.com/2011/09/when-reactive-framework-meets-f-30.html
Rather than taking IObservable<'T> directly my computational expression has a type of:
type MyType<'a,'b> = MyType of (IObservable<'a> -> IObservable<'b>)
let extract (MyType t) = t
Combinators then take on the form:
let where (f: 'b -> bool) (m:MyType<_,'b>) = MyType(fun input -> (extract m input).Where(f))
Within the expression itself, I often need to reference back to previous values that have been fed into the stream. In order to do so, I've defined a MyType which maintains a rolling immutable list of the n most recent values.
let history n =
MyType(fun input ->
Observable.Create(fun (o:IObserver<_>) ->
let buffer = new History<_>(n)
o.OnNext(HistoryReadOnly(buffer))
input.Subscribe(buffer.Push, o.OnError, o.OnCompleted)
)
)
With this, I can now do something like:
let f = obs {
let! history = history 20
// Run some other types, and possibly do something with history
}
I am finding that I am using this history quite frequently, ideally I would want to have this embedded directly into IObservable<'a>. Obviously I can't do that. So my question is, what is a reasonable way to introduce this concept of history that I have here. Should I be extending IObservable<'T> (not sure how to do that), wrapping the IObservable<'T>?
I appreciate any suggestions.
Edit: Added full example code.
open System
open System.Collections.Generic
open System.Reactive.Subjects
open System.Reactive.Linq
// Container function
type MyType<'a,'b> = MyType of (IObservable<'a> -> IObservable<'b>)
let extract (MyType t) = t
// Mini Builder
let internal mbind (myTypeB:MyType<'a,'b>) (f:'b -> MyType<'a,'c>) =
MyType(fun input ->
let obsB = extract myTypeB input
let myTypeC= fun resB -> extract (f resB) input
obsB.SelectMany(myTypeC)
)
type MyTypeBuilder() =
member x.Bind (m,f) = mbind m f
member x.Combine (a,b) = MyType(fun input -> (extract a input).Concat(extract b input))
member x.Yield (r) = MyType(fun input -> Observable.Return(r))
member x.YieldFrom (m:MyType<_,_>) = m
member x.Zero() = MyType(fun input -> Observable.Empty())
member x.Delay(f:unit -> MyType<'a,'b>) = f()
let mtypeBuilder = new MyTypeBuilder()
// Combinators
let simplehistory =
MyType(fun input ->
Observable.Create(fun (o:IObserver<_>) ->
let buffer = new List<_>()
o.OnNext(buffer)
input.Subscribe(buffer.Add, o.OnError, o.OnCompleted)
)
)
let where (f: 'b -> bool) m = MyType(fun input -> (extract m input).Where(f))
let take (n:int) m = MyType(fun input -> (extract m input).Take(n))
let buffer m = MyType(fun input -> (extract m input).Buffer(1))
let stream = MyType(id)
// Example
let myTypeResult (t:MyType<'a,'b>) (input:'a[]) = (extract t (input.ToObservable().Publish().RefCount())).ToArray().Single()
let dat = [|1 .. 20|]
let example = mtypeBuilder {
let! history = simplehistory
let! someEven = stream |> where(fun v -> v % 2 = 0) // Foreach Even
let! firstValAfterPrevMatch = stream |> take 1 // Potentially where a buffer operation would run, all values here are after i.e. we cant get values before last match
let! odd = stream |> where(fun v -> v % 2 = 1) |> take 2 // Take 2 odds that follow it
yield (history.[history.Count - 1], history.[0], someEven,firstValAfterPrevMatch, odd) // Return the last visited item in our stream, the very first item, an even, the first value after the even and an odd
}
let result = myTypeResult example dat
val result : (int * int * int * int * int) [] =
[|(5, 1, 2, 3, 5); (7, 1, 2, 3, 7); (7, 1, 4, 5, 7); (9, 1, 4, 5, 9);
(9, 1, 6, 7, 9); (11, 1, 6, 7, 11); (11, 1, 8, 9, 11); (13, 1, 8, 9, 13);
(13, 1, 10, 11, 13); (15, 1, 10, 11, 15); (15, 1, 12, 13, 15);
(17, 1, 12, 13, 17); (17, 1, 14, 15, 17); (19, 1, 14, 15, 19);
(19, 1, 16, 17, 19)|]
Using the standard Rx workflow builder, you can create a function history that handles your example use case:
let history (io:IObservable<_>) =
io.Scan(new List<_>(), (fun l t -> l.Add t; l)).Distinct()
let io = new Subject<int>()
let newio = rx { let! history = history io
let! even = io.Where(fun v -> v % 2 = 0)
let! next = io.Take 1
let! odd = io.Where(fun v -> v % 2 = 1).Take 2
yield (history.Last(), history.[0], even, next, odd) }
newio.Subscribe(printfn "%O") |> ignore
for i = 1 to 20 do
io.OnNext i
Extending that to provide history length limits should be trivial. Was there a specific reason you need to define your own type/builder, or was doing that just a means to attain something like this?
Here's an example with combinators. You just have to define the observable outside the rx block. You could get history to work differently with immutable histories rather than a persistent list, so whatever fits your needs.
let history (io:IObservable<_>) =
io.Scan(new List<_>(), (fun l t -> l.Add t; l))
let newest (hist:'a List) = hist.Last()
let extract (ioHist:'a List IObservable) = ioHist.Select newest
let take (i:int) (ioHist: 'a List IObservable) = ioHist.Take i
let where (f: 'a -> bool) (ioHist: 'a List IObservable) = ioHist.Where(fun hist -> f(newest hist))
let io = new Subject<int>()
let history1 = history io
let newio =
rx { let! hist = history1.Distinct()
let! even = extract (history1 |> where (fun v -> v % 2 = 0))
let! next = extract (history1 |> take 1)
let! odd = extract (history1 |> where (fun v -> v % 2 = 1) |> take 2)
yield (hist.Last(), hist.[0], even, next, odd) }
You can use Observable.Buffer to do this already.
Sorry for the C# my F# hat is not thinking today.
IObservable<int> source = ...
IOBservable<IList<int>> buffered = source.Buffer(5,1)
will create you a stream of lists.
Or try to use buffer in LINQ which is more like F# query expressions
Console.WriteLine ("START");
var source = new List<int> () { 1, 2, 3, 4, 5 }.ToObservable ();
// LINQ C#'s Monad sugar
var r =
from buffer in source.Buffer (3, 1)
from x in buffer
from y in buffer
select new { x,y};
r.Subscribe (o=>Console.WriteLine (o.x + " " + o.y));
Console.WriteLine ("END");
Note from in LINQ is exactly/almost the same as let! in an f# query expression. The result is below. Also note how I am using buffer later in the expression just like you could in an f# query expression.
START
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
2 2
2 3
2 4
3 2
3 3
3 4
4 2
4 3
4 4
3 3
3 4
3 5
4 3
4 4
4 5
5 3
5 4
5 5
4 4
4 5
5 4
5 5
5 5
END
Sorry, my F# is extremely rusty, but perhaps you are looking for the Scan operator. It will push values to an accumulator as the source produces them and then you can use this accumulator to produce the next value for your projection.
Here (in C#, apologies) we take a sequence of [0..10] which produces these value 100ms apart, and we return a running Sum.
var source = Observable.Interval(TimeSpan.FromMilliseconds(100))
.Take(10);
source.Scan(
new List<long>(), //Seed value
(acc, value)=> //Accumulator function
{
acc.Add(value);
return acc;
}
)
.Select(accumate=>accumate.Sum())
which produces the values [0,1,3,6,10,15,21,28,36,45] 100ms apart.
I would think with this tool you can manage your History of values (by adding them to a history/accumulator) and then using this History in the Select to project the value that is appropriate.

Is there a technical difference between placing a second argument on a new indented line vs the same line?

Consider the two examples below:
let myList = [0..10]
List.map (fun x -> x + 5)
(List.filter (fun x -> x % 3 = 0) myList)
and
let myList = [0..10]
List.map (fun x -> x + 5) (List.filter (fun x -> x % 3 = 0) myList)
Both examples produce the same result:
val myList : int list = [0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
val it : int list = [5; 8; 11; 14]
F# being a white-space sensitive language, is there technically a difference between these two examples?
I think F# Code Formatting Guidelines is very helpful for you, especially the first section about General rules for indentation.
Here is a relevant excerpt from the page:
When you break long lines, the continuation of the line must be indented farther than the enclosing construct. For example, function arguments must be indented farther than the first character of the function name, as shown in the following code.
let someFunction param1 param2 =
let result = myFunction1 param1
param2
result * 100
So indentation in the first example helps F# compiler parse your example correctly.
F# being a white-space sensitive language, is there technically a difference between these two examples?
No. Two code fragments have the same meaning here; the only difference is readability. I prefer the first one since my eyes don't have to go to far right to read the whole function.
Sometimes when a line is too long, you could reorder arguments using pipes and break that line to multiple ones:
myList
|> List.filter (fun x -> x % 3 = 0)
|> List.map (fun x -> x + 5)
UPDATE:
I took some time to aggregate information from different sources and wrote up a comprehensive guide to F# Formatting Conventions; you might want to look into it.

Type inference in pattern match over list

I'm stuck with trying to create a function that will do the following:
let p = [1, 2, 4, 2, 1]
let v = 8
then I want to go over the elements in a until I find the index i of the one where all elements up to and including i are greater or equal than v. So in this case it should return 4, because 1+2+4 < 8 and 1+2+4+2 > 8. So there 4th element, value of 2 puts the total over 8.
(some background: I want to do monte carlo, where I have a list of probabilies that add up to 1. Then I pass a random number between 0 and 1 to have it pick one of the possible future states. Simple example here with ints)
What I have so far is this:
let p = [1, 2, 4, 2, 1]
let pick (v:int) (l:int list) =
let rec sub (i:int) (acc:int) (l2:int list) =
match l2 with
| h::t -> if acc+h >= v then i else sub(i+1, acc+h, t)
| _ -> failwith "total list didn't amount to " + v
sub 0 0 l
pick 8 p
But it gives the following error on the bit sub(i+1, acc+h, t):
error FS0001: This expression was expected to have type
int
but here has type
int -> int list -> int
But I'm not passing the function sub itself, I'm calling it complete with arguments and brackets and all, so why doesn't it return int, the result of the function?
How do I make it return the result of the function?
Thanks in advance,
Gert-Jan
you give the 3-tuple (i+1,acc+h,t) where curried function is supposted to be:
| h::t -> if acc+h >= v then i else sub (i+1) (acc+h) t
Try this.
First, p will be understood as [(1, 2, 4, 2, 1);] which is an (int*int*int*int*int) list with only one element. p as an int list should be [1; 2; 4; 2; 1].
Second, sub(i+1, acc+h, t) in line 6 should be called in the curried form, not in the tuple form. The correction is sub (i+1) (acc+h) t.

Return value in F# - incomplete construct

I've trying to learn F#. I'm a complete beginner, so this might be a walkover for you guys :)
I have the following function:
let removeEven l =
let n = List.length l;
let list_ = [];
let seq_ = seq { for x in 1..n do if x % 2 <> 0 then yield List.nth l (x-1)}
for x in seq_ do
let list_ = list_ # [x];
list_;
It takes a list, and return a new list containing all the numbers, which is placed at an odd index in the original list, so removeEven [x1;x2;x3] = [x1;x3]
However, I get my already favourite error-message: Incomplete construct at or before this point in expression...
If I add a print to the end of the line, instead of list_:
...
print_any list_;
the problem is fixed. But I do not want to print the list, I want to return it!
What causes this? Why can't I return my list?
To answer your question first, the compiler complains because there is a problem inside the for loop. In F#, let serves to declare values (that are immutable and cannot be changed later in the program). It isn't a statement as in C# - let can be only used as part of another expression. For example:
let n = 10
n + n
Actually means that you want the n symbol to refer to the value 10 in the expression n + n. The problem with your code is that you're using let without any expression (probably because you want to use mutable variables):
for x in seq_ do
let list_ = list_ # [x] // This isn't assignment!
list_
The problematic line is an incomplete expression - using let in this way isn't allowed, because it doesn't contain any expression (the list_ value will not be accessed from any code). You can use mutable variable to correct your code:
let mutable list_ = [] // declared as 'mutable'
let seq_ = seq { for x in 1..n do if x % 2 <> 0 then yield List.nth l (x-1)}
for x in seq_ do
list_ <- list_ # [x] // assignment using '<-'
Now, this should work, but it isn't really functional, because you're using imperative mutation. Moreover, appending elements using # is really inefficient thing to do in functional languages. So, if you want to make your code functional, you'll probably need to use different approach. Both of the other answers show a great approach, although I prefer the example by Joel, because indexing into a list (in the solution by Chaos) also isn't very functional (there is no pointer arithmetic, so it will be also slower).
Probably the most classical functional solution would be to use the List.fold function, which aggregates all elements of the list into a single result, walking from the left to the right:
[1;2;3;4;5]
|> List.fold (fun (flag, res) el ->
if flag then (not flag, el::res) else (not flag, res)) (true, [])
|> snd |> List.rev
Here, the state used during the aggregation is a Boolean flag specifying whether to include the next element (during each step, we flip the flag by returning not flag). The second element is the list aggregated so far (we add element by el::res only when the flag is set. After fold returns, we use snd to get the second element of the tuple (the aggregated list) and reverse it using List.rev, because it was collected in the reversed order (this is more efficient than appending to the end using res#[el]).
Edit: If I understand your requirements correctly, here's a version of your function done functional rather than imperative style, that removes elements with odd indexes.
let removeEven list =
list
|> Seq.mapi (fun i x -> (i, x))
|> Seq.filter (fun (i, x) -> i % 2 = 0)
|> Seq.map snd
|> List.ofSeq
> removeEven ['a'; 'b'; 'c'; 'd'];;
val it : char list = ['a'; 'c']
I think this is what you are looking for.
let removeEven list =
let maxIndex = (List.length list) - 1;
seq { for i in 0..2..maxIndex -> list.[i] }
|> Seq.toList
Tests
val removeEven : 'a list -> 'a list
> removeEven [1;2;3;4;5;6];;
val it : int list = [1; 3; 5]
> removeEven [1;2;3;4;5];;
val it : int list = [1; 3; 5]
> removeEven [1;2;3;4];;
val it : int list = [1; 3]
> removeEven [1;2;3];;
val it : int list = [1; 3]
> removeEven [1;2];;
val it : int list = [1]
> removeEven [1];;
val it : int list = [1]
You can try a pattern-matching approach. I haven't used F# in a while and I can't test things right now, but it would be something like this:
let rec curse sofar ls =
match ls with
| even :: odd :: tl -> curse (even :: sofar) tl
| even :: [] -> curse (even :: sofar) []
| [] -> List.rev sofar
curse [] [ 1; 2; 3; 4; 5 ]
This recursively picks off the even elements. I think. I would probably use Joel Mueller's approach though. I don't remember if there is an index-based filter function, but that would probably be the ideal to use, or to make if it doesn't exist in the libraries.
But in general lists aren't really meant as index-type things. That's what arrays are for. If you consider what kind of algorithm would require a list having its even elements removed, maybe it's possible that in the steps prior to this requirement, the elements can be paired up in tuples, like this:
[ (1,2); (3,4) ]
That would make it trivial to get the even-"indexed" elements out:
thelist |> List.map fst // take first element from each tuple
There's a variety of options if the input list isn't guaranteed to have an even number of elements.
Yet another alternative, which (by my reckoning) is slightly slower than Joel's, but it's shorter :)
let removeEven list =
list
|> Seq.mapi (fun i x -> (i, x))
|> Seq.choose (fun (i,x) -> if i % 2 = 0 then Some(x) else None)
|> List.ofSeq

Resources