How to implement automatic generalization in a simple function

I created the following statement to help with safe division.

let (/!) a b = 
    if b = 0 then 0 
    else a / b

      

The problem is that it only works with integers, and I would like this function to work with any numeric primitive (int, float, decimal, etc.).

I've read about automatic generalization but it hasn't quite dived in and I'm not sure if it's even the right direction.

How do you generalize this operator?

Thank,

Joe

+3


source to share


1 answer


Hi this is a bit of a hidden gem, but what you are looking for is this:

let inline (/!) (a : ^a) (b : ^a) : ^a = 
    if b = LanguagePrimitives.GenericZero 
    then LanguagePrimitives.GenericZero 
    else a / b

      

btw: it has this monster type:

val inline ( /! ) :
  a: ^a -> b: ^a ->  ^a
    when  ^a : equality and  ^a : (static member get_Zero : ->  ^a) and
          ^a : (static member ( / ) :  ^a *  ^a ->  ^a)

      

(that's why I don't like to write this in the ad;))

As you can see, there is support for generic numeric code, but this is not often discussed (F # has some type of type in which they are built in - here's an example, others like comparable

and so on).

Tomas wrote a good article about this: Writing Generic Numeric Code



PS you don't need it either ^a

- but I like writing the signature - and even if you can do it:

let inline (/!) a b = 
    if b = LanguagePrimitives.GenericZero 
    then LanguagePrimitives.GenericZero 
    else a / b

val inline ( /! ) :
  a: ^a -> b: ^b ->  ^c
    when ( ^a or  ^b) : (static member ( / ) :  ^a *  ^b ->  ^c) and
          ^b : (static member get_Zero : ->  ^b) and  ^b : equality and
          ^c : (static member get_Zero : ->  ^c)

      

it won't help you, as real division operators usually only have one type for both arguments - and as I said: I like to underscore types over argument names;)

fun fact

you can bypass the tag GenericZero

like this:

> let inline (/!) a b = if b = (b-b) then (b-b) else a/b;;

val inline ( /! ) :
  a: ^a -> b: ^b ->  ^b
    when ( ^a or  ^b) : (static member ( / ) :  ^a *  ^b ->  ^b) and
          ^b : (static member ( - ) :  ^b *  ^b ->  ^b) and  ^b : equality

      

(To be on the safe side: you might run into problems with certain types / numbers here;))

+8


source







All Articles