Why is the signature different for these two functions? - f#

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

Related

Creating a random fractional number in F#

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

Definition style preferences

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.

Function composition argument error

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).

In F#, what is the meaning of parentheses around operator type? [duplicate]

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).

Does F# treat parameter matching differently when there is only one input parameter?

The function matching is based on the definition of the file in F#:
let f2 x y = x + y
let value5 = f2 10 20
let value = f2(10, 20) <-- Error
let f3 (x, y) = x + y
let value6 = f3(10, 20)
let value = f3 10 20 <-- Error
However, I can use in both ways with one parameter with F#:
let f n = n + 10
let value3 = f 10
let value4 = f(10)
Why is this? Does F# treat parameter matching differently when there is only one input parameter?
As ashays correctly explains, the two ways of declaring functions are different. You can see that by looking at the type signature. Here is an F# interactive session:
> let f1 (x, y) = x + y;;
val f1 : int * int -> int
> let f2 x y = x + y;;
val f2 : int -> int -> int
The first function takes a tuple of type int * int and returns int. When calling it, you need to specify the tuple (which is just a single value):
// Using tuple directly as the argument
f1 (1, 2)
// .. or by declaring tuple value first
let tup = (1, 2)
f1 tup
The type of the second function is int -> int -> int, which is the same thing as int -> (int -> int). This means that it is a function that takes int and returns a function that takes int and returns int. This form is called curried form and it allows you to use partial function application as demonstrated by ashays. In fact, the call:
f2 1 2
// Could be written as:
(f2 1) 2
My suspection is that this has something to do with tuples and currying. Basically, a tuple of one item becomes a singular item again, however in our other two cases we have the following:
The first case (f2) is actually a function that takes a single value (x) and returns a value that takes another single function. Here we can see the use of currying from f2 to add10
let add10 = f2 10
let myVal = add10 20
We get an error with the tuple because we have not defined it in such a way as to receive a tuple. In the second example, we have a similar issue, where we defined the function to take a tuple of two values, and it knows how to process those values, but we have passed it two values now instead of the one (a tuple) that it was expecting, and thus we receive an error.
Once again, in the last case, we have a tuple of a single item and so f x and f(x) are effectively the same thing.
I could be wrong in my reasoning, but I believe that's why you're getting your errors.

Resources