I'm extremely new to F# and was playing around with the stack calculator on the F# for fun and profit (excellent site). I was trying to figure out how to have a test project and class. I have a test class with this method:
open NUnit.Framework
open FSharpDoodles.MainProgram
[<TestFixture>]
type ProgramTests()=
[<Test>]
member self.FirstTest()=
// Create some stacks
let EMPTY = StackContents []
let try1 = push 1.0 EMPTY // OK
let try2_partial = push 1.0 // OK
let try2 = try2_partial EMPTY // OK - does same as ONE below
let stackWith1 = ONE EMPTY // FAILS: ONE is null
()
The code it is testing is thus:
module FSharpDoodles.MainProgram
type Stack = StackContents of float list
let push x (StackContents contents) =
StackContents ( x::contents )
let ONE = push 1.0
So, if I'm calling a function and getting a value (call to push), it works. And if I create a partially applied function in the class (try2_partial), that works. But when I'm referencing ONE, which is returning a partially applied function, ONE is null.
Why is that?
The Rest of The Story
I'm using NCrunch as my test runner. It is entirely possible that it is causing a problem.
Edit
As suggested by John, I tried this in FSI and get the same issue. Below is the progressive application of the same test code:
open FSharpDoodles.MainProgram
let EMPTY = StackContents [];;
val EMPTY : FSharpDoodles.MainProgram.Stack = StackContents []
> let try1 = push 1.0 EMPTY;;
val try1 : Stack = StackContents [1.0]
> let try2_partial = push 1.0;;
val try2_partial : (Stack -> Stack)
> let try2 = try2_partial EMPTY;;
val try2 : Stack = StackContents [1.0]
> let stackWith1 = ONE EMPTY;;
System.NullReferenceException: Object reference not set to an instance of an object.
at <StartupCode$FSI_0006>.$FSI_0006.main@()
Stopped due to error
I made a reference to the SUT for FSI under Tools|Options -> F# Interactive, F# Interactive options. I used -r and referenced the assembly in debug\bin.
As I mentioned, I very new to this F# stuff and I might be making some very rookie mistake related to how I'm putting together either of the modules.
Update 2
Based on John's comment, I tried moving the code from an .exe to a .dll (library). It worked fine. So, the issue is related to referencing the .exe. So the question now evolves into why this makes a difference (exe vs dll)?
The reason it didn't work is that I was referencing an EXE and not a DLL. Same code in a DLL works fine. Thanks to John Palmer question for getting me to investigate that angle and then for providing the explanation (see the comments).