i have something like
type A =
| X of string
| Y of int
i have a sequence of X types, [X "foo"; X "boo"; X "moo"]
is there a shortcut for开发者_StackOverflow社区 doing a map to convert it to ["foo"; "boo"; "moo"]
without doing a match?
Thanks!
I wouldn't generally use a solution that doesn't handle all cases of the pattern matching (e.g. when using fun (X str) -> ...
. It is always a good idea to add handler, even if it just reported a more informative error (such as, that the case was unexpected because it was filtered before).
You can extend kvb's solution using the function
syntax (which is like fun
with pattern matching):
List.map (function (X s) -> s | _ -> failwith "Unexpected case")
Alternatively, if you wanted to ignore Y
values (so that [X "a"; Y 1; X "b"]
becomes ["a"; "b"]
) you can use List.choose
function:
List.choose (function (X s) -> Some s | _ -> None)
To write this using list comprehensions, you'd need to use full-blown pattern matching using match
, so it would be a bit longer than using higher-order functions.
You can use this:
List.map (fun (X s) -> s)
This does perform a match behind the scenes, but the syntax is nicer. You'll get a warning since the pattern is partial (that is, the function clearly won't be able to handle Y _
instances).
Just for grins, you could do this:
let get<'T> = function
| X s -> box s :?> 'T
| Y i -> box i :?> 'T
To get a list of X
or Y
, but not both.
[X "foo"; X "boo"; X "moo"] |> List.map get<string>
[Y 0; Y 1; Y 2] |> List.map get<int>
[Y 0; X "boo"; Y 2] |> List.map get<int> //oh snap!
If you're okay with boxed values, this works for mixed lists:
let get = function
| X s -> box s
| Y i -> box i
[Y 0; X "boo"; Y 2] |> List.map get //no problem
I'm assuming you're interested in unorthodox solutions since you're asking how to avoid pattern matching. ;-)
Here is another general-purpose, yet baroque, solution.
Similar to @kvb's solution, you can use a list comprehension with an incomplete pattern match:
let xl = [X "foo"; X "boo"; X "moo"]
[for X s in xl -> s]
You must match. If you do that a lot, define functions getX and getY:
let getX (X v) = v
let getY (Y v) = v
But be aware that they will raise exceptions if given a value of the wrong case.
精彩评论