4

Say we got a very simple function

let fn a = a.ToString()

It's type gets inferred as a -> string However, passing a unit value to the function results in a NullReferenceException.

In case of simple functions like above, this might be worked around easily, but I'm actually in a more complex scenario:

let eitherToHttp e = 
    match e with
    | Either.Ok v ->        OK (v.ToString()) 
    | Either.Bad reason ->  reasonToErrorCode reason

The type of this is Either<'a, RejectReason> -> WebPart (what WebPart and Either actually are is irrelevant here)

In a scenario where the type of e is Either<unit, RejectReason> the function throws exactly like in the simple scenario.

How can I overcome this in a nice way? Should the types be inferred as generic if in fact this does not work for ALL types?

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
Grzegorz Sławecki
  • 1,727
  • 14
  • 27

2 Answers2

6

Use the built-in string function instead of calling ToString on the object:

> string 42;;
val it : string = "42"
> string ();;
val it : string = ""
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • I'm moving the accepted answer tag, since, the other answer, while less elegant produces a generic function, while `string` operator seems to be somehow limited, please see my other SO question for the details: http://stackoverflow.com/questions/41371190/type-inference-on-tostring-vs-string-operator – Grzegorz Sławecki Dec 28 '16 at 23:37
3

You can do something like this:

let fn a = match box a with
           | null -> ""
           | _ -> a.ToString()

This compiles down to just a null check on a before attempting to call ToString.

Ringil
  • 6,277
  • 2
  • 23
  • 37
  • Please read my comment to Mark's answer to know why this one was accepted. – Grzegorz Sławecki Dec 28 '16 at 23:38
  • To be fair you could inline his solution and it might work better. You could try it out – Ringil Dec 29 '16 at 00:33
  • I did try it just a moment ago. It seems, that using `inline` is kind of contagious. Using it either makes the function that calls an `inline` function to be `inline` as well, or causes it not to be generic. Look in my question to the `eitherToHttp` function which I'd like to be as generic as possible. Inlining it appears somehow not suitable to me (but maybe I'm wrong). – Grzegorz Sławecki Dec 29 '16 at 13:12