Search code examples
f#inlinegeneric-programming

Function working for all numerical data types


I've written a simple function that reverses a given number:

let reverseNumber x =
    let rec innerFunc acc elem =
        if elem = 0
            then acc
            else 
                let rem = elem % 10
                innerFunc (10 * acc + rem) (elem / 10)

    innerFunc 0 x

The problem is it works only with ints. For e.g. int64 I need to create another version that uses 0L and 10L instead of 0 and 10 respectively.

I've heard it's possible to write more generic functions using inline keyword and LanguagePrimitives, but the latter doesn't contain neither reminder operation nor 'GenericTen' (although this might be obtained by 'GenericOne + GenericOne + ... ).

Could you help ?


Solution

  • Ignoring the completeness of @kvb's linked answers, this is the minimal work to make it generic:

    module NumericLiteralG =
        let inline FromZero () = LanguagePrimitives.GenericZero
        let inline FromOne () = LanguagePrimitives.GenericOne
    
    let inline reverseNumber (x:^a) =
        let ten:^a = 1G + 1G + 1G + 1G + 1G + 1G + 1G + 1G + 1G + 1G
        let rec innerFunc (acc:^a) (elem:^a) =
            if elem = 0G then acc
            else
                let (rem:^a) = elem % ten
                innerFunc (ten * acc + rem) (elem / ten)
        innerFunc 0G x
    

    The type annotations are not strictly necessary, and are only present to reduce the type constraints listed in IntelliSense; the code would work identically without them.