F# GreaterThanZero passing int or decimal - f#

I want to create a function that check if the passed value is greater than zero.
The passed value can be an int or a decimal (ideally a "numeric value").
In the immediate I just started with this:
type number =
| I of int
| D of decimal
type Checker () =
member this.Validate value =
match value with
| I x when x > 0 -> "ok"
| D x when x > 0m -> "ok"
| _ -> "error"
let a = 1f
let b = 1m
//let a_IsValid = Checker().Validate(a) // does not compile, expect number (not int)
//let b_IsValid = Checker().Validate(b) // does not compile, expect number (not decimal)
Found not immediate to pass a "number" so tried something different...
I found this article (http://tomasp.net/blog/fsharp-generic-numeric.aspx/) and I thought
"static member constraint" is the perfect solution for me.
A basic example works as expected:
let inline divideByTwo value =
LanguagePrimitives.DivideByInt value 2
divideByTwo 1f |> ignore
divideByTwo 1m |> ignore
but a different scenario found me very surprised:
type Calculator () =
let divideByTwo value =
LanguagePrimitives.DivideByInt value 2
member this.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
member this.ValidateGeneric value =
match LanguagePrimitives.GenericGreaterThan value 0m with
| true -> "ok"
| _ -> "error"
//let half = Calculator().DivideByTwo(1) // DivideByInt does not support int !!
// cannot use both the following, the first one will "force" the type, and the other will not work
let a_half = Calculator().DivideByTwo(1f) // ok if used before the "decimal" version
let b_half = Calculator().DivideByTwo(1m) // ok only if comment the previous one
It seems not to work when I want to use more than one type for the passing value.
More than that, the function I need (GenericGreaterThan) seems to have another "limitation", explained below.
The example in the article use DivideByInt and, as the name said, it divide the passed value by an int, a well defined type.
LanguagePrimitives.GenericGreaterThan needs 2 parameters, a passed value and a fixed one to compare to. The signature of the function as only one generic type for both, so if you pass a type 'T it expect the second one to be 'T too.
I just wants to compare with zero without passing it, but using "0" forced my value
to be an int and using "0m" force the value to be a decimal.
There is a simple way to have a function that check if a "numeric" value is greater than "zero" ?
Should I use obj and box it .... or use cast ... or stop trying and just use a different function for every type I need ?
[UPDATE]
I tried to use the LanguagePrimitives.GenericZero as suggested but still not able to have a working solution for my particular scenario.
I created a new issue here: F# - Compare LanguagePrimitives.GenericZero with a value passed on the class contructor .

Comparing against zero generically is actually quite simple. The following function should work for any numeric type:
let inline isPositive x =
x > LanguagePrimitives.GenericZero
isPositive 1.0 |> printfn "%A" // true
isPositive 1m |> printfn "%A" // true
Dividing by two generically is also pretty easy. You just have to define your own generic two, since it's not a built-in primitive:
let inline divideByTwo x =
let two =
LanguagePrimitives.GenericOne
+ LanguagePrimitives.GenericOne
x / two
divideByTwo 5.0 |> printfn "%A" // 2.5
divideByTwo 4m |> printfn "%A" // 2

there lots of things here.
your first example didn't work because you needed to wrap your number inside the type number (I assume you realise this? but didnt want it to work like that?)
type Checker () =
member this.Validate value =
match value with
| I x when x > 0 -> "ok"
| D x when x > 0m -> "ok"
| _ -> "error"
let a = I 1
let b = D 1m
let a_IsValid = Checker().Validate(a)
let b_IsValid = Checker().Validate(b)
your second example is that in doesnt support divide by int?
yes what is the value of 1/2? its not an int, so thats correct by design.
the third question seems to be that this code doesnt compile and run?
type Calculator () =
member inline _.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
let b_half = Calculator().DivideByTwo(1m) // ok for me
let a_half = Calculator().DivideByTwo(1f) // ok for me
but this works for me.
The fourth question appears to be the need to use static constraints to test if something is > 0?
but 0 (as in mathematics) is a different thing in different number systems, its generic too so you need LanguagePrimitives.GenericZero. putting that all together we get
type Calculator () =
member inline _.DivideByTwo value =
LanguagePrimitives.DivideByInt value 2
member inline _.ValidateGeneric value =
match LanguagePrimitives.GenericGreaterThan
value
LanguagePrimitives.GenericZero with
| true -> "ok"
| _ -> "error"
let b_half = Calculator().DivideByTwo(1m)
let a_half = Calculator().DivideByTwo(1f)
let y = Calculator().ValidateGeneric(1m)
let z = Calculator().ValidateGeneric(1f)
as for the divide by 1/2 question, you may need to think what you want it to do? really the input type is defined by what output type you want? decimal? float? etc

Related

making type aliases non interchangeable in F#

Here is an example:
type T =
TimeSpan
let x (y: T) =
printfn $"{y}"
let a:TimeSpan = TimeSpan.FromSeconds(3)
let b:T = TimeSpan.FromSeconds(3)
let a' = x a
let b' = x b
In this case, I want to make a type which is identical to TimeSpan but is NOT TimeSpan. I would like the ability to cast between one another, but not be equivalent when it comes to function signatures.
For example, the x function takes a type T, so the line:
let a' = x a
shouldn't compile because it passes a TimeSpan
but the line:
let b' = x b
is passing a type T and should compile.
Is there some simple and elegant way to achieve this? the goal for this is to be able to use TimeSpan, but constrain the options to some specific values.
Right now I'm using an enum that needs to be convert to TimeSpan and then TimeSpans get reconvert to the enum if they exist in the enum. It's rather ugly.
I want to make a type which is identical to TimeSpan but is NOT TimeSpan. I would like the ability to cast between one another, but not be equivalent when it comes to function signatures.
That's not possible in F#, but the usual way to accomplish something like it is with single-case unions, such as:
type T = T of TimeSpan
let x (T y) =
printfn "%A" y // y is the inner TimeSpan value
let a:TimeSpan = TimeSpan.FromSeconds(3.0)
let b:T = TimeSpan.FromSeconds(3.0) |> T
let a' = x a // doesn't compile
let b' = x b
The general issue I think you're dealing with here is called "primitive obsession".
You can either use a single cased DU, or you can use units of measure to do this. UMX specifically supports timespans.
https://github.com/fsprojects/FSharp.UMX

A function that accepts multiple types

I am fairly new to f#, but I want to know if it is possible to make a function that accepts multiple types of variables.
let add x y = x + y
let integer = add 1 2
let word = add "He" "llo"
Once a function use a type of variable it cannot accept another one.
You need to read about statically resolved type parameters and inline functions. It allows to create functions which may take any type that supports operation and/or have member. So your add function should be defined this way:
let inline add x y = x + y
Don't overuse inlined functions because their code inlined in call site and may increase assembly size, but may increase performance (test each case, don't make predictions!). Also inlined function are supported only by F# compiler and may not work with other languages (important when designing libraries).
Example of SRTP magic:
let inline (|Parsed|_|) (str: string) =
let mutable value = Unchecked.defaultof<_>
let parsed = ( ^a : (static member TryParse : string * byref< ^a> -> bool) (str, &value))
if parsed then
Some value
else
None
match "123.3" with
| Parsed 123 -> printfn "int 123"
| Parsed 123.4m -> printfn "decimal 123.4"
| Parsed 123.3 -> printfn "double 123.3"
// | Parsed "123.3" -> printfn "string 123.3" // compile error because string don't have TryParse static member
| s -> printfn "unmatched %s" s

How to make F# modules configurable (or make similar effect, like object properties)

Let's say I have these code:
namespace global
module NumeracyProblemsInTen=
module private Random=
let private a=lazy System.Random()
let getRandom()=a.Force()
let next()=getRandom().Next()
let lessThan exclusiveMax=getRandom().Next exclusiveMax
let pick seq=
assert(not<|Seq.isEmpty seq)
lessThan<|Seq.length seq|>Seq.item<|seq
module UsedNumbers=
let min,max=1,9 // *want to make these data variable*
let numbers={min..max}
let atLeast a=numbers|>Seq.skipWhile((>)a)
let atMost a=numbers|>Seq.takeWhile((>=)a)
module Random=
let private pick=Random.pick
let pickNumber()=pick numbers
let atMost=atMost>>pick
open UsedNumbers
module AdditionInTen=
module Addends=
let max=max-min
let numbers={min..max}
let pick()=Random.pick numbers
open Addends
let quiz()=
let addend=pick()
addend,Random.atMost<|min+max-addend
let calc(addend,another)=addend+another
module MultiplyInTen=
let quiz()=
let multipiler=Random.pickNumber()
multipiler,Random.pick{min..max/multipiler}
let calc(multipiler,another)=multipiler*another
module SubtractionInTen=
let minSubtrahend,minResult=min,min
let minMinuend=minSubtrahend+minResult
let minuends=atLeast minMinuend
let quiz()=
let minuend=Random.pick minuends
minuend,Random.pick{minSubtrahend..minuend-minResult}
let calc(minuend,subtrahend)=minuend-subtrahend
module DeviditionInTen=
let devisible devidend deviser=devidend%deviser=0
let findDevisers devidend=numbers|>Seq.filter(devisible devidend)
let findDeviditions devidend=findDevisers devidend|>Seq.map(fun deviser->devidend,deviser)
let problems=Seq.collect findDeviditions numbers
let quiz()=Random.pick problems
let calc(devidend,deviser)=devidend/deviser
type Problem=Addition of int*int|Subtraction of int*int|Multiply of int*int|Devidition of int*int
let quiz()=
let quizers=[AdditionInTen.quiz>>Addition;SubtractionInTen.quiz>>Subtraction;
MultiplyInTen.quiz>>Multiply;DeviditionInTen.quiz>>Devidition]
quizers|>Random.pick<|()
let calc problem=
match problem with
|Addition(addend,another)->AdditionInTen.calc(addend,another)
|Subtraction(minuend,subtrahend)->SubtractionInTen.calc(minuend,subtrahend)
|Multiply(multipiler,another)->MultiplyInTen.calc(multipiler,another)
|Devidition(devidend,deviser)->DeviditionInTen.calc(devidend,deviser)
module NumeracyProblemsUnderOneHundred=
module UsedNumbers=
let min,max=1,99
// ...
// ...
// ...
// OMG! Do I must copy all the previous code here?
If I use oo/types, I can simply define Max as a property, is there a good way to resolve the same scene without object/types but only modules/immutable bindings way? A bit of more complex scene should be also considered, more configurable data, with more usage in different ways.
So, it seems to me that your code is designed to generate a random mathematical operation which you can then calculate the result of. I found this code quite difficult to decipher, it appears that you're trying to use modules like object oriented classes which contain internal state and that isn't really a good way to think about them.
You can achieve much more granular code reuse by thinking about smaller, composable, units of code.
Here is my attempt at this problem:
type Range = {Min : int; Max : int}
type Problem=
|Addition of int*int
|Subtraction of int*int
|Multiplication of int*int
|Division of int*int
module NumeracyProblems =
let private rnd = System.Random()
let randomInRange range = rnd.Next(range.Min, range.Max+1)
let isInRange range x = x >= range.Min && x <= range.Max
let randomOpGen() =
match randomInRange {Min = 0; Max = 3} with
|0 -> Addition
|1 -> Subtraction
|2 -> Multiplication
|3 -> Division
let calc = function
|Addition (v1, v2) -> Some(v1 + v2)
|Subtraction (v1, v2) -> Some(v1 - v2)
|Multiplication (v1, v2) -> Some(v1 * v2)
|Division (v1, v2) ->
match v1 % v2 = 0 with
|true -> Some(v1 / v2)
|false -> None
let quiz range =
let op = randomOpCtor()
let optionInRange x =
match isInRange range x with
|true -> Some x
|false -> None
Seq.initInfinite (fun _ -> randomInRange range, randomInRange range)
|> Seq.map (op)
|> Seq.find (Option.isSome << Option.bind (optionInRange) << calc)
I've created a Range record to contain the range data I'm going to be working with.
My randomInRange function generates a random number within the specified range.
My isInRange function determines whether a given value is within the supplied range.
My randomOpGen function generates a number in the range of 0-3 and then generates a random type constructor for Problem: Addition when the random value is 1, Subtraction when 2, etc.
(You might wonder why I've defined this function with a unit argument rather than just accepting the tuple, the answer is so that I can get it to generate operators with equal likelihood later.)
My calc function resolves the arithmetic by performing the appropriate operation. I've modified the result of this function so that it handles integer division by returning Some result for cases where the remainder is 0 and None otherwise. All the other computations always return Some result.
quiz is where the magic happens.
First I generate a random operator, this will be the same for every element in the sequence later - hence the importance of the () I mentioned earlier.
I generate an infinite sequence of integer tuples from the supplied range and, using map, generate an operation (the one I created earlier) on each of these tuples.
I then use Seq.find to find the first occurrence of a result that's both within the range that I specified and has a valid result value.
Now let's try this code:
let x = NumeracyProblems.quiz {Min = 1; Max = 9}
x
NumeracyProblems.calc x;;
val x : Problem = Addition (2,7)
val it : int option = Some 9
Now let's change the range
let x = NumeracyProblems.quiz {Min = 1; Max = 99}
x
NumeracyProblems.calc x
val x : Problem = Division (56,2)
val it : int option = Some 28
As you can see, this version of the code is completely agnostic to the integer range.

F# type definition with expression

Is it possible to express something like this:
type id = int > 0
I know its not possible to do statically, since this would mean F# has dependent types. In C# I'm used to do this sort of thing with code contracts and get a runtime enforcement. I'm looking for something similiar here.
Thanks
EDIT:
Thank you for all the answers which have various pros and cons. At the monent I'm only using a small subset of F#, a subset of the ocaml core that lends itself easily to program proofs. So no classes.
Contrary to what others said, I would suggest not using classes here, if I understood your problem correctly.
Since the value is immutable, we need applying constraint only once. Any wrapper classes would be an overhead and load GC. Instead, a simple function will do the job:
let inline constrained predicate errormessage value =
if not (predicate value)
then invalidArg "value" errormessage
else value
let positive =
constrained (fun x -> x > 0) "Value must be positive"
let int1 = positive 5 // OK
let int2 = positive -3 // ArgumentException
You can do the same for other types:
let mustBeLong =
constrained (fun (x:string) -> x.Length > 3) "String must be long"
let str1 = mustBeLong "foobar" // OK
let str2 = mustBeLong "baz" // ArgumentException
Using the same within a struct:
type Point2D =
struct
val X: int
val Y: int
new(x: int, y: int) = { X = positive x; Y = positive y }
end
let point1 = Point2D(5, 3) // OK
let point2 = Point2D(5, -2) // ArgumentException
Define it as a union type:
type Id = Id of int
and shadow the constructor with another function:
let Id n =
assert(n > 0)
Id n
In F#, you have to resort to classes and check arguments inside constructors. Other types such as discriminated unions, records and structs have implicit constructors which you can't easily alter.
type Id(i: int) =
do if i <= 0 then
invalidArg "i" "the argument has to be a positive integer"
member x.Value = i
Pattern matching doesn't play nicely with classes. You can remedy the problem using active patterns:
let (|Id|) (id: Id) = id.Value
let id = Id(1)
match id with
| Id 1 -> printfn "matched"
| _ -> printfn "unmatched"
You could create a generic class like so:
type verify<'t>(t:'t,cond) =
let mutable tval = t
let _verify v = if not (cond v) then failwith "bad argument"
do _verify tval
member x.get() = tval
member x.set v =
_verify v
tval <- v
then you can use it with
verify(1,fun t -> t>0)
using .set will recheck the condition.

How to downcast from obj to option<obj>?

I have a function that takes a parameter of type object and needs to downcast it to an option<obj>.
member s.Bind(x : obj, rest) =
let x = x :?> Option<obj>
If I pass (for example) an Option<string> as x, the last line throws the exception: Unable to cast object of type 'Microsoft.FSharp.Core.FSharpOption'1[System.String]' to type 'Microsoft.FSharp.Core.FSharpOption'1[System.Object]'.
Or, if I try a type test:
member s.Bind(x : obj, rest) =
match x with
| :? option<obj> as x1 -> ... // Do stuff with x1
| _ -> failwith "Invalid type"
then x never matches option<obj>.
In order to make this work, I currently have to specify the type the option contains (e.g. if the function is passed an option<string>, and I downcast the parameter to that rather than option<obj>, the function works.
Is there a way I can downcast the parameter to option<obj> without specifying what type the option contains? I've tried option<_>, option<#obj>, and option<'a> with the same results.
By way of background, the parameter needs to be of type obj because I'm writing an interface for a monad, so Bind needs to bind values of different types depending on the monad that implements the interface. This particular monad is a continuation monad, so it just wants to make sure the parameter is Some(x) and not None, then pass x on to rest. (The reason I need the interface is because I'm writing a monad transformer and I need a way to tell it that its parameter monads implement bind and return.)
Update: I managed to get around this by upcasting the contents of the option before it becomes a parameter to this function, but I'm still curious to know if I can type-test or cast an object (or generic parameter) to an option without worrying about what type the option contains (assuming of course the cast is valid, i.e. the object really is an option).
There isn't any nice way to solve this problem currently.
The issue is that you'd need to introduce a new generic type parameter in the pattern matching (when matching against option<'a>), but F# only allows you to define generic type parameters in function declarations. So, your only solution is to use some Reflection tricks. For example, you can define an active pattern that hides this:
let (|SomeObj|_|) =
let ty = typedefof<option<_>>
fun (a:obj) ->
let aty = a.GetType()
let v = aty.GetProperty("Value")
if aty.IsGenericType && aty.GetGenericTypeDefinition() = ty then
if a = null then None
else Some(v.GetValue(a, [| |]))
else None
This will give you None or Some containing obj for any option type:
let bind (x : obj) rest =
match x with
| SomeObj(x1) -> rest x1
| _ -> failwith "Invalid type"
bind(Some 1) (fun n -> 10 * (n :?> int))
I am not certain why you need to get your input as obj, but if your input is an Option<_>, then it is easy:
member t.Bind (x : 'a option, rest : obj option -> 'b) =
let x = // val x : obj option
x
|> Option.bind (box >> Some)
rest x
To answer your last question: you can use a slight variation of Tomas' code if you need a general-purpose way to check for options without boxing values beforehand:
let (|Option|_|) value =
if obj.ReferenceEquals(value, null) then None
else
let typ = value.GetType()
if typ.IsGenericType && typ.GetGenericTypeDefinition() = typedefof<option<_>> then
let opt : option<_> = (box >> unbox) value
Some opt.Value
else None
//val ( |Option|_| ) : 'a -> 'b option
let getValue = function
| Option x -> x
| _ -> failwith "Not an option"
let a1 : int = getValue (Some 42)
let a2 : string = getValue (Some "foo")
let a3 : string = getValue (Some 42) //InvalidCastException
let a4 : int = getValue 42 //Failure("Not an option")

Resources