Jonathan Allen
Jonathan Allen

Reputation: 70307

How do I cast a "string" into a "option<string>"

I have a function declared as

let GetLength (value : option<string>) = 
    if value.IsSome then value.Value.Length else 0

And I have the variable

let a : string = "tom"

How do I pass a to the function GetLength?

Upvotes: 7

Views: 4947

Answers (4)

Stephen Hosking
Stephen Hosking

Reputation: 1465

The accepted answer doesn't compile, and produces...

GetLength Some a;;

^^^^^^^^^^^^^^ error FS0003: This value is not a function and cannot be applied

F# thinks you are building a function (GetLength Some) to apply to the value a. That is because it's a functional language.

The correct form is

GetLength (Some a);;

Upvotes: 11

Uros Dimitrijevic
Uros Dimitrijevic

Reputation: 2651

To answer the general question of casting 'a to option<'a>, if you wanted to do it safely without just applying the object to the Some constructor, there is a simple function that I would use:

let to_option = function
  | null -> None
  | obj -> Some obj

Upvotes: 4

dahlbyk
dahlbyk

Reputation: 77540

An alternative to parentheses:

GetLength <| Some a

I think it's important to address this question:

Why would anyone willing type 18 tokens over 3 lines when you can get the exact same thing using 12 tokens on one line?

Writing code isn't just about conciseness - it's also about readability and maintainability. Suppose you need to handle the case where a is null. With pattern matching, you could go from this:

let GetLength (value : string option) =
    match value with
    | Some s -> s.Length
    | _ -> 0

To this:

let GetLength (value : string option) =
    match value with
    | Some s when s <> null -> s.Length
    | _ -> 0

To an F# programmer, the meaning is clear. To fix your implementation would look something like this:

let GetLength (value : option<string>) = 
    if value.IsSome && value.Value <> null then value.Value.Length else 0

The result might be the same, but I don't find it particularly easy to see, at a glance, what's happening.

It's fine if pattern matching doesn't resonate with you, but the extra "cost" in the simple case is often made up for many times over as the logic evolves.

Upvotes: 7

Zifre
Zifre

Reputation: 26998

You don't cast it. You need to use the Some constructor:

GetLength Some a

Upvotes: 10

Related Questions