Reputation: 63
I am currently studying F# and at the same time, a bit struggling to get the hang of how discriminated unions and records exactly work.
I'd like to know how I can update some values from a list of type <'T>?
type Position =
| Location of (int * int)
type Ship =
{
Position : Position;
Projectiles : List<Position>;
}
I create an instance of a ship:
let aShip =
{
Position: Location(1,5);
Projectiles: [Location(1,1);Location(2,5)]
}
Now, I tried to loop over the projectiles, but I get this:
for elem in aShip.Projectiles do
printfn "%A" elem
// prints out
Location(1,1)
Location(2,5)
But I only like to get the values (1,1) and (2,5) back, how would I achieve this?
Upvotes: 3
Views: 137
Reputation: 80765
Discriminated unions can be destructured by providing a pattern with some places in it occupied by identifiers. The compiler will then generate code that tries to match this pattern to the data, and bind data points to appropriate identifiers. For example:
let loc = Location (1,2)
let (Location (x,y)) = loc
For the second line, the compiler will generate code to the effect of "make sure this is a Location
, then bind the first int to name x
, and the second int to name y
"
Alternatively, you can use more verbose match
syntax:
let x = match loc with Location(x,y) -> x
For your specific case, this is overkill, but for discriminated unions with more than one case, match
is the only way to handle them all, for example:
type Position =
| Location of int*int
| Unknown
let xOrZero =
match loc with
| Location(x,y) -> x
| Unknown -> 0
Above examples demonstrate how patterns can appear in let
-bindings and within match
expressions, but this is not all. In F# pretty much anything that you'd think of as "variable declaration" is actually a pattern. It's just most of the time patterns are trivial, as in let x = 5
, but they don't have to be - e.g. let x,y = 5,6
The corollary from the above is that the elem
in for elem in ...
is also a pattern. Which means that you can destructure the element in place:
for Location(x,y) in aShip.Projectiles do
printfn "%d,%d" x y
Or, if you'd like to extract the pair as a whole, rather than x
and y
individually, that is also possible:
for Location xy in aShip.Projectiles do
printfn "%A" xy
Upvotes: 5