6

Given the following record in F#:

type Model =
   { Text: string option }

What is the F# equivalent of C#'s,

    string.IsNullOrEmpty(Model.Text)

TIA

Alan Wayne
  • 5,122
  • 10
  • 52
  • 95

3 Answers3

5

Assuming you want to treat a None value as null or empty you can use Option.fold:

let m = { Text = Some "label" }
m.Text |> Option.fold (fun _ s -> String.IsNullOrEmpty(s)) true

a drawback of using fold is the ignored accumulator parameter in the accumulator function. In this case you just need a function to apply in the case of Some and a default value to use if the option is None e.g.

let getOr ifNone f = function
    | None -> ifNone
    | Some(x) -> f x

then you can use

m.Text |> getOr true String.IsNullOrEmpty
Lee
  • 142,018
  • 20
  • 234
  • 287
  • I've worked a lot in F# and never seen `Option.fold` used so I don't think it's idiomatic. This is a bit confusing for me. I have to stare at it for a while to know exactly what it's doing. – TheQuickBrownFox Nov 19 '20 at 12:32
  • ok, but it is quite idiomatic of functional programming in general, "fold" (and unfold) is a basic building block of almost all non trivial algorirhtms. I just think...its an array/seq/list with 1 or 0 elements in it. – MrD at KookerellaLtd Nov 20 '20 at 12:10
  • Your `getOr` function almost exists already, albeit with inverse argument order; `defaultArg (m.Text |> Option.map String.IsNullOrEmpty) true` – kaefer Nov 20 '20 at 21:27
  • It's a bit of an old topic but I'm new at F# and I'm getting the error "The type 'string' does not match the type 'string option'" for both of your suggestions. It baffles me why I can't just do `let result = if string.IsNullOrEmpty(s) then foo else bar`. How do I express this? – Diana Mar 23 '22 at 13:16
  • @Diana - What's the type of `s` in your code? It sounds like it's a `string`, in which case you should be able to call `String.IsNullOrEmpty` directly, and your example should work. – Lee Mar 23 '22 at 14:33
  • @Lee s comes from `let s = Environment.GetEnvironmentVariable("BLA")` which should be `string` according to intellisense but I get this error regardless – Diana Mar 23 '22 at 19:40
5

Lees answer is probably the most functionally idiomatic i.e. when you want to process a data type, you can squash it into an answer using fold. But note that you can drop the "s", to make it

m.Text |> Option.fold (fun _ -> String.IsNullOrEmpty) true

if folding isnt something that you are yet at ease with then a more set oriented version would be, "are all of them empty?" (if there are none, then they are)

m.Text |> Option.forall (fun s -> String.IsNullOrEmpty s)

or in short hand

m.Text |> Option.forall String.IsNullOrEmpty

(I'd personally use this one)

MrD at KookerellaLtd
  • 2,412
  • 1
  • 15
  • 17
2

The Option.toObj function converts an option containing a reference type to a nullable object. A None will be converted to null. It's quite useful for interop with APIs expecting nulls:

model.Text |> Option.toObj |> String.IsNullOrEmpty
TheQuickBrownFox
  • 10,544
  • 1
  • 22
  • 35