Premise: I thought that the piping operator is nothing but syntactic sugar, thus x |> f should be exactly the same as f(x).
Analogously, I thought that f (fun x -> foo) is equivalent to let g = fun x -> foo; f g
But apparently there are differences that I do not understand.
Example 1:
static member contents =
let files = Directory.EnumerateFiles (__SOURCE_DIRECTORY__+ @"\foo\bar.txt")
let fileList = List.ofSeq files
fileList |> List.map (fun f -> TestCaseData(f).SetName(""))
This works fine: TestCaseData expects an arg:obj which is matched by f which in turn in inferred to be a string since fileList is a list of file names.
However the following does not work
static member contents =
let files = Directory.EnumerateFiles (__SOURCE_DIRECTORY__+ @"\foo\bar.txt")
let fileList = List.ofSeq files
List.map (fun f -> TestCaseData(f).SetName("")) fileList
Nothing but the last line has changed. Suddenly f is inferred as obj [] and TestCaseData requires an argument of type obj [] and hence I get an error
Error 1 Type mismatch. Expecting a obj [] list but given a string list
The type 'obj []' does not match the type 'string'
I would have thought that both snippets are equivalent in produce correct code but only the first does?!
Example 2:
[<TestCase("nonsense", TestName="Nonsense")>]
member x.InvalidInputs str =
let lexbuf = Microsoft.FSharp.Text.Lexing.LexBuffer<char>.FromString(str)
Assert.Throws<FatalError> (fun () -> ParsePkg.parse "Dummy path" lexbuf |> ignore)
|> ignore
Above everything works fine.
[<TestCase("nonsense", TestName="Nonsense")>]
member x.InvalidInputs str =
let lexbuf = Microsoft.FSharp.Text.Lexing.LexBuffer<char>.FromString(str)
let ff = fun () -> ParsePkg.parse "Dummy path" lexbuf |> ignore
Assert.Throws<FatalError> (ff)
|> ignore
As you see, all I did was pull out the argument of the assertion by first defining let ff = ... (for readability reasons, say) and suddenly the compiler points to the (ff) argument and complains:
Error 2 This expression was expected to have type TestDelegate but here has type unit -> unit
TestDelegate is a type of NUnit that I am using here and it happens to coincide with unit->unit so I'd assume it would be unified anyway but that does not even matter. Why at all is it possible that the type changes, since again I believe to have done a purely syntactic replacement?!