Reputation: 2952
I created a nested discriminated union:
type hsAlgorithm = HS256 | HS384 | HS512
type rsAlgorithm = RS256 | RS384 | RS512
type esAlgorithm = ES256 | ES384 | ES512
type Algorithm =
| HMAC of hsAlgorithm
| RSA of rsAlgorithm
| ECDsa of esAlgorithm
I create an Algorithm
variable:
> let a = HMAC HS256;;
val a: Algorithm = HMAC HS256
Is there a property to directly access HS256
?
I wrote a function which matches the algorithm and returns the value but I wonder whether I can access the value directly. Below is my function to match the value:
let extractAlgorithm (algorithm: Algorithm) =
match algorithm with
| HMAC x -> x.ToString()
| RSA x -> x.ToString()
| ECDsa x -> x.ToString()
Upvotes: 2
Views: 125
Reputation: 10624
The simple answer to your question is "no". Each DU case can contain different types so there isn't generally a way to access the value inside each one in a common way. If you find yourself needing this then you could probably find a better type structure. Here's a possible alternative:
type SHA =
| SHA256
| SHA384
| SHA512
member this.IdSuffix =
match this with
| SHA256 -> "256"
| SHA384 -> "384"
| SHA512 -> "512"
type AlgoType =
| HMAC
| RSA
| ECDsa
member this.IdPrefix =
match this with
| HMAC -> "HS"
| RSA -> "RS"
| ECDsa -> "ES"
// Use a record to define an algorithm, because every algorithm has a type AND a "HS"
type Algorithm =
{ AlgoType : AlgoType
SHA : SHA }
member this.Id = this.AlgoType.IdPrefix + this.SHA.IdSuffix
let algo = { AlgoType = HMAC; SHA = SHA256 }
algo.Id // returns "HS256"
Side note: Avoid using .ToString()
or string
on DUs. It's actually very slow and has caused significant performance issues for me in the past, even when working on relatively simple applications. See here for more details. I've included members on the types above to build up the algorithm's ID string.
Upvotes: 1
Reputation: 57149
but I wonder whether I can access the value directly.
You can make nested match patterns, like this:
let extractAlgorithm (algorithm: Algorithm) =
match algorithm with
| HMAC(HS384) -> "HS"
| RSA x -> x.ToString()
| ECDsa x -> x.ToString()
If you mean: how to access all these x
as a single x
, then the answer is: it depends. Only if all x
have the same type, you can write something like the following (this won't work with your code):
let extractAlgorithm (algorithm: Algorithm) =
match algorithm with
| HMAC x
| RSA x
| ECDsa x -> x.ToString()
But since F# is a type-safe language, and you have defined three different types for each of the HMAC|RSA|ECDSa
types, it won't let you do that.
If all you want is access to ToString()
, just use the string
function. You can just do: string algorithm
. And more in general, you shouldn't use .ToString()
as it is unsafe and may raise an NRE, where string
never fails.
Upvotes: 1