I have the following code snippet:
let add n x = x + n
let times n x = x * n
let addTimes = add 5 >> times 5
addTimes 4
and this works without any problem. But when I change like this
let add n x = x + n
let times n x = x * n
let addTimes = add >> times
addTimes 4
I've got the compiling error
error FS0071: Type constraint mismatch when applying the default type '(int -> int)' for a type inference variable. Expecting a type supporting the operator '*' but given a function type. You may be missing an argument to a function. Consider adding further type constraints
Why?
The signature of (>>) is ('T1 -> 'T2) -> ('T2 -> 'T3) -> 'T1 -> 'T3. I.e., it composes two unary functions – you are attempting to supply two binary functions, which is valid in general (though arguably not useful, or at the least unclear), but not for your function types:
Given that (f >> g) x is equivalent to g(f(x)), what would the expected outcome be when f is binary? In your case, x (int) is partially-applied to add (int -> int -> int), and that partial application ((int -> int)) is passed to times (also int -> int -> int), which obviously expects an int as its first parameter rather than the function type (int -> int).
Related
What is the difference between these two functions?
let increment1 x = x +1 // (int -> 'a) -> 'a // why??
let increment2 x = x + 1 // int -> int // this is clear
The lack of space between + and 1 changes the meaning. When there is a space, it reads as operator + applied to argument 1, but without a space it means "positive one", similarly to how -1 means "negative one".
And since +1 is a number of type int, then x +1 must be a function application, applying function x to the argument +1, and therefore x must be of type int -> 'a for some generic type 'a
I was trying to create a random fractional number as follows:
type Fraction=
{
num: int
den: int
}
let makeRandomFraction i =
let n= fun i -> System.Random(i).Next(-50, 51)
let d= fun i -> System.Random(i*3).Next(-50, 51)
{num=n; den=d}
but I am getting an error:
error FS0001: This expression was expected to have type
'int'
but here has type
'int -> int'
Could you please explain the error and the correct way of doing the required.
The error is saying that you're passing a function (of type int -> int) where an int is expected. You can see this more clearly in something like:
let add a b = a + b
let inc x = x + 1
inc add
// ^^^
// This expression was expected to have type 'int' but has type 'int -> int -> int'
The solution here is just to take out the fun i -> parts. That's the (other) syntax for lambdas, but since your i variable is already in scope there's no need to create a function around it.
Out of curiosity, do you have any requirements on what range and distribution of fractions do you want your function to generate? The way the code is currently written - by composing two random numbers in a range -50 .. 50, you will get a distribution with most numbers being close to zero.
Here is a simple histogram built using the XPlot F# library:
open XPlot.GoogleCharts
type Fraction=
{ num: int
den: int }
let makeRandomFraction i =
let n = System.Random(i).Next(-50, 51)
let d = System.Random(i*3).Next(-50, 51)
{num=n; den=d}
[ for i in 0 .. 100000 -> let f = makeRandomFraction i in float f.num / float f.den ]
|> Seq.filter (System.Double.IsInfinity >> not)
|> Seq.countBy (fun f -> int f)
|> Chart.Column
What is the preferable style for F# definitions?
The book I am studying makes regular use the following style:
let foo = fun x y ->
let aux1 = fun z -> z * 2
in aux1 x +
let aux2 = fun q -> q * 3
in aux2 y;;
On the other side, when I look for information on the web, it is most likely to meet something like:
let foo (x: int) (y: int) =
let aux1 (z:int) = z * 2
in aux1 x +
let aux2 (q: int) = q * 3
in aux2 y;;
On the Guide I failed to find a reference about it. Is it a matter that goes beyond "mere style"? There are efficiency implications behind these two approaches?
What does your experience suggest?
As a general rule, F# function definitions tend to do one of two things:
Define as few types as possible (let foo x y = ...). This is the case for most functions. Or...
Explicitly define the types of each argument and the return type (let foo (x : int) (y : int) : int = ....
Style #2 is rare, and I've usually seen it for functions that are explicitly part of the API of a module, and that have /// comments to provide documentation as well. For internal functions, though, the typeless variant is usually used, since F#'s type inference works so well.
Also, as s952163 pointed out in a comment, the in keyword is almost never used anymore, since the #light style makes it unnecessary. I'd expect to see your sample code written as follows in modern F# style:
let foo x y =
let aux1 z = z * 2
let aux2 q = q * 3
(aux1 x) + (aux2 y)
No ;; necessary, either, unless you're typing into the F# Interactive console. If you're using VS Code + Ionide, and highlighting segments of code and pressing Alt + Enter to send them to F# Interactive, then you don't need any ;; separators because Ionide adds them automatically.
I found evidence suggesting that the first style, even if today unconventional, is intrinsically connected to currying and anonymous functions.
Currying is a powerful characteristic of F#, where, I remember, every function could take only one parameter. For example:
let add x y = x + y
val add: int -> int -> int
The signature is interpreted as add is a function that takes two integers as input and return an integer.
When compile time comes, the function is interpreted like:
let add2 = fun x -> fun y -> x + y
val add2: int -> int -> int
where val add2: int -> int -> int is semantically equivalent to val add: (int -> (int -> int))
By providing an argument to add2, such as 6, it returns fun y -> 6 + y, which is another function waiting for its argument, while x is replaced by 6.
Currying means that every argument actually returns a separate function: that's why when we call a function with only few of its parameters returns another function.
If I got it correctly, the more common F# syntax of the second example, let add x y = x + y, could be thought like syntactic sugar for the explicit currying style shown above.
I am having trouble with the following:
let safeDiv x y =
match (x,y) with
| (_, Some 0) -> None
| (Some xx, Some yy) -> Some (xx/yy)
| _ -> None
When I go to run this simple function in the interactive window of Visual Studio like so:
safeDiv 4 2
I get the following error...
This expression was expected to have type int option but here has type int.
Could it be I'm meant to use safeDiv Some(4) Some(2)? This doesn't work either...
Ok, this is overkill but I actually did something similar to this recently.
First I defined a computation expression builder for the option type:
type OptionBuilder() =
member this.Bind(x, f) = Option.bind f x
member this.Return(x) = Some x
member this.ReturnFrom(x) = x
let opt = new OptionBuilder()
And then I defined a function sub of type float -> float -> float option
let sub x y = if y = 0.0 then None else Some (x / y)
And finally I used the OptionBuilder to define saveDiv as float option -> float option -> float option
let safeDiv x y = opt { let! a = x
let! b = y
return! sub a b }
You can read more about computation expressions on wikibooks: http://en.wikibooks.org/wiki/F_Sharp_Programming/Computation_Expressions
And if you want to dive deeper into the theory behind this, you can read this paper by Tomas Petricek and Don Syme: http://www.cl.cam.ac.uk/~tp322/drafts/notations.pdf
Your second version was close.
It should be
safeDiv (Some(4)) (Some(2))
The extra brackets are required to make sure that functions are applied in the correct order.
You constructed a function that has the signature safeDiv : int option -> int option -> int option. You need to use an entry like safeDiv (Some 4) (Some 2) to use your function as is.
The problem is in the matching of (4, 2), of type int*int, with the expressions (_, Some 0) and (Some xx, Some yy). The whole function can be simplified:
let safeDiv x y =
match (x,y) with
| (_, 0) -> None
| (_, _) -> Some (x/y)
Making the following call valid
safeDiv 4 2
I have three functions that ought to be equal:
let add1 x = x + 1
let add2 = (+) 1
let add3 = (fun x -> x + 1)
Why do the types of these methods differ?
add1 and add3 are int -> int, but add2 is (int -> int).
They all work as expected, I am just curious as to why FSI presents them differently?
This is typically an unimportant distinction, but if you're really curious, see the Arity Conformance for Values section of the F# spec.
My quick summary would be that (int -> int) is a superset of int -> int. Since add1 and add3 are syntactic functions, they are inferred to have the more specific type int -> int, while add2 is a function value and is therefore inferred to have the type (int -> int) (and cannot be treated as an int -> int).