Creating a random fractional number in F# - 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

Related

What is the leading ? is F# type signature?

When I hover certain methods that come from C# libraries in F#, some of the parameters start with a ?. I'm unfamiliar with this syntax. Does this mean nullable?
Here is an example from hovering the SetStatus method on the Activity class where the description parameter is preceded by a ?.
The optional parameters in F# are declared with question marks in the declaration of the function:
https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/parameters-and-arguments#optional-parameters
What is interesting that the optionality expressed this way turns them to actual options of the base type, however there are differences: The options are 'active' only within the scope of the member method, and you have to pass the underlying type variable (or nothing in this case)
type Test() =
member this.fn (?i : int) =
match i with
| Some x -> -x
| None -> 0
let t = new Test()
let r1 = t.fn()
printfn "%d" r1
let r2 = t.fn(4)
printfn "%d" r2
If you declare your member method as int option, you can't omit the parameter despite identical implementation of the method otherwise:
type Test() =
member this.fn (i : int option) =
match i with
| Some x -> -x
| None -> 0
let t = new Test()
let r1 = t.fn()
printfn "%d" r1
let r2 = t.fn(4)
printfn "%d" r2
Here's the output:
/home/jdoodle.fs(9,14): error FS0001: This expression was expected to have type
'int option'
but here has type
'unit'
/home/jdoodle.fs(12,15): error FS0001: This expression was expected to have type
'int option'
but here has type
'int'
In order to make it working, you have to pass int option to the method:
let r1 = t.fn(None)
printfn "%d" r1
let r2 = t.fn(Some 4)
printfn "%d" r

Why is the signature different for these two functions?

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

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

Int Option instead of Int in F#

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

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

Resources