In Haskell, if I have a list of union typed values like this:
example :: [Either Int Char]
example = [Left 3, Right 'b', Left 6, Left 9, Right 'c']
I can use a little "trick" to extract all the results matching some specific pattern:
lefts :: [Int]
lefts = [l | Left l <- example]
However, if I try to translate this to F#, I get an error:
let lefts = [for Choice1Of2 l in example -> l]
~~~~~~~~~~~~
Incomplete pattern matches on this expression. (...)
This makes a lot of sense (it might even be better behavior than silently ignoring Right
values like Haskell does!), but in F#, is there some convenient way to extract (and match on) all values matching a certain pattern in a list/sequence?
In F# if you don't match against all cases you will get a warn, in all scenarios.
So you can write the match with both cases inside the expression, but for your example rather than comprehensions I would use the function List.choose
:
let example = [Choice2Of2 3; Choice1Of2 'b'; Choice2Of2 6; Choice2Of2 9; Choice1Of2 'c']
List.choose (function (Choice1Of2 x) -> Some x | _ -> None) example
// val it : char list = ['b'; 'c']
This function is handy for those cases.
I think the closest thing you can do using F# list expressions is something like this:
let lefts example =
[ for e in example do
match e with Choice1Of2 l -> yield l | _ -> () ]
If I understand the Haskell code correctly, the part after |
is used not just as an extractor, but also as a filter - implicitly skipping over all things that do not match the pattern.
F# does not have the same kind of concept in list expressions, so you have to be more verbose. Here, we just iterate over all items using for
and then we explicitly use yield
to produce a new value for each Choice1Of2
in the source list (and we just skip over anything else).
Depending on what you're doing, using List.choose
(as mentioned in Gustavo's answer) might be easier. But the above is probably closest you can get to the Haskell's comprehension syntax.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With