Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to refer to the first element of a tuple encapsulated in a single-case discriminated union

Tags:

f#

Suppose you have a type like this:

type Corner = Corner of int*int

and then some variable:

let corner = Corner (1,1)

Is it possible to get the value of the first element of the tuple, something like:

fst corner

Looks like some kind of unwrapping to int*int is necessary.

like image 498
Horia Toma Avatar asked Dec 19 '15 19:12

Horia Toma


3 Answers

The answer provided by @Foole is good, but from the comment I get the impression that you don't like having to 'declare' the temporary variable first. This can indeed feel cumbersome if all you want to do is to pull out the first value and then pipe it to another function.

There's no built-in facility that I'm aware of that lets you do this automatically. Consider that the Corner type given above is a degenerate case of a Discriminated Union (DU). Normally, DUs have more cases, and they are often heterogeneous in shape.

There can be good reasons to have a single-case DU such as Corner, but then it often makes sense to also supply various 'helper' functions to make working with that type smoother.

In the case of the Corner type, you could define functions such as:

let cornerX (Corner(x, _)) = x

let cornerY (Corner(_, y)) = y

Here, I've assumed that Corner models a coordinate, but if you'd like, you can also name the functions fst and snd. You can also put them in a dedicated module, if you rather prefer that.

This will enable you to extract and pipe a value from a Corner value without the hassle of a temporary variable:

> corner |> cornerX |> ((*) 10) |> string;;
val it : string = "10"

where corner is defined as in the OP.

like image 61
Mark Seemann Avatar answered Nov 10 '22 18:11

Mark Seemann


I assume that was meant to be

type Corner = Corner of int*int

In which case, this will get the first value:

let (Corner(first,_)) = corner
like image 22
Foole Avatar answered Nov 10 '22 17:11

Foole


As already mentioned, it's not possible to get the first discriminated union case without naming it. But here's quite a concise way to do it:

Corner (1,1) |> function Corner (x,_) -> x

This uses the function keyword, which creates a function with one parameter and jumps straight into a pattern match on that parameter. Since there's only one case to match on it fits neatly into one line.

like image 22
TheQuickBrownFox Avatar answered Nov 10 '22 16:11

TheQuickBrownFox