Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unwrap F# single-case discriminated union tuple type

We can unwrap type like type Address = Address of string using unwrapping function like

let unwrapAddress (Address a) = a
let addr = Address "sdf"
let str = unwrapAddress addr

so str will be of type string, but if there is type like this approach willn't work:

type Composite = Composite of integer:int * someStr:string
let unwrap (Composite c) = c

will produce error

let unwrap (Composite c) = c;;
------------^^^^^^^^^^^
error FS0019: This constructor is applied to 1 argument(s) but expects 2

Can I somehow unwrap composite types to a simple tuple?

like image 484
Shishkin Pavel Avatar asked Jun 15 '17 18:06

Shishkin Pavel


1 Answers

In your case, you can write:

type Composite = Composite of int * string 

let unwrap (Composite (a, b)) = a, b

which corresponds to:

let unwrap x = 
    match x with
    | Composite (a, b) -> a, b

What's happening here is that F# allows you to deconstruct function arguments inline using arbitrarily complex pattern matching. This is often mentioned when introducing single case DU's, but it's rarely followed to the conclusion, which leads people to believe single case DU's are somehow special that way.

In fact, you can use it when you have multiple cases (as long as each case binds the same set of variables):

type Composite = Composite of int * string | JustString of string

let unwrapString (Composite (_, s) | JustString s) = s

But most of the time, you'd pattern match on simpler types, like tuples:

let f (a, b, c) = ...

or even more curiously:

let f () = ...

Here () is a pattern match on the lone value of unit type - rather than some kind of "visual marker for a parameterless function", as it's often described.

like image 152
scrwtp Avatar answered Nov 07 '22 03:11

scrwtp