Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic string to integer conversion in F#

Tags:

generics

f#

I'm implementing a simple conversion string to integer convertor in F#; the logic is, e.g from string to uint32:

let inline sToUint s =
    let mutable v = 0u

    for c in s do
        v <- v * 10u + uint32 c - uint32 '0'

    v

Now I would like to use this implementation for other integer types, e.g. uint64. How can I implement a single generic function to do that?

Thank for all, SRTP (as used in the answers) is what I need for such a situation. The following implementation is just slightly changed from the answer of @Brian Berns

// (char -> ^a) -> (string -> ^b)
let inline sToNum f =
    let tenTimes v = (v <<< 3) + (v <<< 1)
    fun (s: string) ->
        let mutable v = Unchecked.defaultof<_>
        for c in s do
            v <- (tenTimes v) + f c - f '0'
        v
like image 639
Ta Thanh Dinh Avatar asked Feb 15 '26 04:02

Ta Thanh Dinh


1 Answers

You can do something like this:

let inline sToNum f =
    let ten = Seq.replicate 10 LanguagePrimitives.GenericOne |> Seq.sum
    fun s ->
        let mutable v = LanguagePrimitives.GenericZero
        for c in s do
            v <- v * ten + f c - f '0'
        v

let sToUint16 = sToNum uint16
let sToUint32 = sToNum uint32
let sToUint64 = sToNum uint64
let sToInt16 = sToNum int16
let sToInt32 = sToNum int32
let sToInt64 = sToNum int64

Test code:

sToUint16 "123" |> printfn "%A"   // 123us
sToUint32 "123" |> printfn "%A"   // 123u
sToUint64 "123" |> printfn "%A"   // 123UL
sToInt16 "123" |> printfn "%A"    // 123s
sToInt32 "123" |> printfn "%A"    // 123
sToInt64 "123" |> printfn "%A"    // 123L

Note that sToNum returns a lambda, so it doesn't have to recompute ten each time. (You could even cache the value of f '0' as well, to shave off a little more time.)

like image 197
Brian Berns Avatar answered Feb 16 '26 21:02

Brian Berns



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!