If I declare a method with no parameters and then call it (in F#-interactive), then I get the expected behaviour: "test" is displayed on screen.
let somefn() =
printfn "test"
>
val somefn : unit -> unit
> somefn();;
test
val it : unit = ()
However, If I declare the method without parentheses, then I get some different behavior:
let somefn =
printfn "test"
>
test
val somefn : unit = ()
> somefn;;
val it : unit = ()
> somefn();;
somefn();;
^^^^^^
C:\...\Local\Temp\stdin(4,1): error FS0003: This value is not a function and cannot be applied.
So what I don't understand:
Why is method declaration without parameters so different than with parameters?
When I declare without parentheses, I got the message: val somefn : unit = (). What does it mean unit = ()? What exactly did I declared now? What sort of entity is somefn now?
It is obviously that now there's an entity called somefn, which points to some executable code. How can I execute that code? can I declare somefn as member of a struct or something and execute it from there?
The comments above answer this question but I'll add some detail.
When you define a function, each parameter is actually a pattern match with only one case. For example you could write:
let somefn 0 = 1
The type of this function is int -> int. The first parameter is inferred to be an int, but this generates a warning because there are other ints that are not being matched on. somefn 0 returns 1, but somefn 1 throws an exception "The match cases were incomplete".
The type unit has only one value: (). It's effectively as a "nothing" value for the input or an output of a function. It has a pattern match that looks exactly like the value (just like [] for an empty list), which is why you can add a unit parameter to any function using (). These functions are all exactly the same:
let somefn () = ()
let somefn (x:unit) = ()
let somefn (_:unit) = ()
When you write a function that doesn't take any parameters, you just add a single unit parameter so that it's a function and not a value, and therefore you delay its execution. Just to drive the point home, you could even add more than one unit parameter, although you would never need to do this:
let somefn () () = ()
// unit -> unit -> unit
Related
When attempting to supply a fake delegate for a method with an optional parameter in a faked object
type MyType () =
abstract B: ?s:string -> unit
default x.B (?s: string) = Option.iter (printfn "Implemented: %s") s
[<Property>]
let doit () =
let a = A.Fake<MyType>()
A.CallTo(fun () -> a.B(ignored())).Invokes(fun s -> Option.iter (printfn "Faked: %s") s)
a.B "Hello"
FakeItEasy complains
FakeItEasy.Configuration.FakeConfigurationException: Argument constraint is of type System.String, but parameter is of type Microsoft.FSharp.Core.FSharpOption`1[System.String]. No call can match this constraint.
Is there a way to make this run without changing the type definition ?
OK, I was able to reproduce your error message by defining ignored as:
let ignored<'t> () = A<'t>.Ignored
The problem is that you've defined a string constraint for an argument that's actually a string option. You can work around this by explicitly naming the parameter ?s when you call the member, like this:
A.CallTo(fun () -> a.B(?s=ignored())).Invokes(fun s -> Option.iter (printfn "Faked: %s") s)
Now the constraint has the correct type, Option<string>, and the code executes without error. Output is:
Faked: Hello
This SO answer has more details about specifying values for optional arguments.
Why are parentheses needed on read_rest_of_csv below?
let read_rest_of_csv() =
csv_data.Add(csv_fileH.ReadFields()) |> ignore
not csv_fileH.EndOfData
while read_rest_of_csv() do ignore None
Without the parentheses, the loop will not terminate.
open System
open System.Threading
open System.Collections.Generic
open System.Linq
open System.Text
open System.Threading.Tasks
open System.IO
open Microsoft.VisualBasic.FileIO
[<EntryPoint>]
let main argv =
let csv_fileH = new TextFieldParser("test1.csv")
csv_fileH.TextFieldType = FieldType.Delimited |> ignore
let x = csv_fileH.SetDelimiters(",")
let csv_data = new List<string[]>()
let eod = csv_fileH.EndOfData
if not eod then
let column_headings = csv_fileH.ReadFields()
csv_data.Add(column_headings) |> ignore
let read_rest_of_csv =
csv_data.Add(csv_fileH.ReadFields()) |> ignore
not csv_fileH.EndOfData
while read_rest_of_csv do ignore None
0
I apologize that I cannot remember where I saw this. I think it was in SO. It's a nice example.
Could this be that without parens I'm dealing with a function object of sorts?
I am indeed coming from not only a C, C++, and C# background, but also an intermediate Clojure background as well. In my case with F# syntax, reading my Haskell manual in a little more detail might have helped, because the syntaxes seem similar.
It seems that people coming from C-family languages (C#, Java, C, C++, JavaScript) are having problems understanding the use of brackets in F#. I certainly had, and it took me some years learning how things work.
In a nutshell, the most basic building block in F# is a value. Values can be let-bound:
let foo = bar
This means that foo is a value, which happens to be equal to bar.
Functions are also values:
// 'a -> 'a * 'a
let f = fun x -> x, x
Here, f is a function that takes some value (x) and returns a tuple with x as both the first and the second element.
That's a bit cumbersome to write, so there's a shorthand for that:
// 'a -> 'a * 'a
let f x = x, x
Notice that there are no brackets in these expressions.
Sometimes you need to adjust the precedence of operators. Just like in maths, 1 + 2 * 3 (which is equivalent to 1 + (2 * 3)) isn't the same as (1 + 2) * 3. In F#, you also use brackets to override precedence. Thus
// 'a -> string * 'a
let f x = someOtherFunction x, x
isn't the same as
// x:'a -> string
let f x = someOtherFunction (x, x)
(in this case, someOtherFunction is a function that returns a string.)
Notice that the brackets don't denote a function call; they're only there to control order of evaluation.
Sometimes, you want to define a function that doesn't take any input. You can't, however, define it like this:
let f = whatever
because that would make it a value that's immediately let-bound to whatever. Instead, you can let the function take a value of the built-in type unit. This type only has a single value, which is written ():
let f () = whatever
This means that f is a function that pattern matches its input against the only known value of unit.
Whenever you invoke f with (), the expression whatever is evaluated and returned.
Without the parentheses, the content executes once and never again. read_rest_of_csv has a type of bool: You are basically saying while true do ignore None.
The parentheses indicate that read_rest_of_csv has type unit -> bool, so every time you invoke it, it reads a row and moves the cursor. Otherwise, it will only do this once.
The answer to your question is that:
let read_rest_of_csv =
csv_data.Add(csv_fileH.ReadFields()) |> ignore
not csv_fileH.EndOfData
is not a function at all. This is no different from:
> let i = 1;;
val i : int = 1
This declares a binding with an integer value. If you want to declare a binding with a function value which takes no parameters, that looks like this:
> let i () = 1;;
val i : unit -> int
The exact same reasoning applies to read_rest_of_csv. Without the parenthesis, you are declaring a binding with type bool. With the parenthesis, you are declaring a binding with type unit->bool i.e. a binding with a function value where the function takes no inputs and returns a bool value.
Based on this kvb's answer, this code compiles (F#4) and runs :
type Untupler = abstract Apply : 'u * 'u -> 'u
let myotherFun arg1 arg2 =
printfn "myotherFun result is : %A %A" arg1 arg2
let myFunction tup1 tup2 (i:Untupler) =
myotherFun (i.Apply tup1) (i.Apply tup2)
let reskvb = myFunction (1,2) ("Hello","World") { new Untupler with member __.Apply (x,y) = snd (x,y) }
But if the last line is replaced by the initial answer :
let reskvb = myFunction (1,2) ("Hello","World") { new Untupler with member __.Apply x = fst x }
then the compiler complains with error FS0768 :
The member 'Apply' does not accept the correct number of arguments, 2 arguments are expected
I do not understand why the compiler seems to fail to infer that x is indeed a tuple. Or is there another issue I am missing ? Thx.
The reason for this is that when you start using interfaces, you move into F#'s support for Object-Oriented Programming, and in F#, all OOP interop methods are tupled by default.
Thus, the Apply method is interpreted as being a method that takes two method arguments, rather than a function that takes a single tuple as input.
I'm trying to understand the variance rules for function types. It seems they don't treat input and output the same (up to duality). Consider this program.
let mk1 s = s |> Seq.iter (fun _ -> ())
// val mk1 : s:seq<'a> -> unit
let mk2 = mk1 : list<int> -> unit // Ok.
let mk3 () = [1]
// val mk3 : unit -> int list
let mk4 = mk3 : unit -> seq<int> // Type mismatch.
This is the error:
Type mismatch. Expecting a
unit -> seq<int>
but given a
unit -> int list
The type 'seq<int>' does not match the type 'int list'
It's my understanding that seq<int> is an interface type, one which int list implements, so I was expecting this cast to go through(*).
Two questions:
Why doesn't it?
Why is the cast producing mk2 ok?
(*) For theorists: I was expecting the elaborator to exhibit dual behaviour on the input and output positions of the function space type constructor. Is that wrong?
You have this:
let mk4 = mk3 : unit -> seq<int>
Which will not compile, the up-cast will happen automatically in the input parameter but never in the output of the function. This is in the spec, section 14.4.2 Implicit Insertion of Flexibility for Uses of Functions and Members.
This means that F# functions whose inferred type includes an unsealed type in argument position may be passed subtypes when called, without the need for explicit upcasts.
This makes possible to define another version of the function which is restricted to a subtype, which are the other cases you're showing.
Interestingly, you can use flexible types to define mk4 as follows:
let mk4 = mk3 : unit -> #seq<int>
It compiles but automatically lifts the type of mk4 up to unit -> int list
This is probably something simple, but I have a .fs file with a simple sample function.
let printHello = printfn "%A" "Hello"
I have set the search path to the .fs file using
>#I "PathToMyFSFile"
I have loaded my file using
>#load "Test.fs"
Which worked fine. Now I want to call the function which actually prints the hello to screen, but thats turning out to be too difficult
> Test.printHello;;
val it : unit = ()
Tried Test.printHello();; as well but doesn't work. How do I actually make it print "Hello" to screen?
your current printHello isn't actually a function. To make it a function you need to do
let printHello() = printfn "%A" "Hello"
noice the (). Then everything should work.
EDIT:
When the compiler sees your definition
let printHello = printfn "%A" "Hello"
it passes it as a simple data term. For example, consider this program:
let printHello = printfn "%A" "Hello"
printfn "World"
printHello
This will print "Hello" then "World". printHello just has unit type, so does nothing. Compare it to
let printHello() = printfn "%A" "Hello"
printfn "World"
printHello()
Here printHello is a function. In this case, the function is only executed when it is explicitly called, so this prints "World" then "Hello".
As John already said, your printHello isn't a function - it is a value of type unit. When you give printfn all the required arguments (as you did), it does the imperative operation and return unit (which is a type with only a single value written as ()). You can see that writing that declaration does the printing immediately:
> let printHello = printfn "%A" "Hello";;
"Hello"
val printHello : unit = ()
When you use printHello later, it simply refers to this unit value (which does not carry any information).
If you want to make it a function (of type unit -> unit) that will do something each time it is executed, then you can use the sample that John posted.
The function printfn was not partially applied, because you gave it all the parameters it required (so it could just print immediately). If you wanted to use partial application, you could use something like:
> let printHello = printfn "%s %s" "Hello";; // Note - didn't give value for second %s
val printHello : string -> unit
Now printHello is a function that waits for the second parameter and then runs:
> printHello "World";;
Hello World
val it : unit = ()
> printHello "F#";;
Hello F#
val it : unit = ()
As has already been said in other answers, "printHello" set to () is unit, the return value of printfn is () , console print is side-effect.
use Lazy:
let printHello = Lazy (fun () ->printfn "%A" "Hello")
DEMO
> Test.printHello.Value;;
"Hello"
val it : unit = ()
> Test.printHello.Value;;
val it : unit = () //only once
use Seq:
let printHello = seq { printfn "%A" "Hello"; yield ()}
DEMO
> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null]
> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null] //many times