How to enumerate a discriminated union in F#? - f#

How can I enumerate through the possible "values" of a discriminated union in F#?
I want to know if is there something like Enum.GetValues(Type) for discriminated unions, tough I am not sure over what kind of data I would enumerate. I would like to generate a list or array of a discriminated union with one item for each option.

Yes, F# has it's own reflection layer build on top of .NET's reflection to help you make sense of types that are specific to F#, like discriminating unions. Here's the code that will let you enumerate a union's cases:
open Microsoft.FSharp.Reflection
type MyDU =
| One
| Two
| Three
let cases = FSharpType.GetUnionCases typeof<MyDU>
for case in cases do printfn "%s" case.Name

If your discriminated union is only made of plain identifiers (no case storing any data, this might be what you need: gist
open Microsoft.FSharp.Reflection
module SimpleUnionCaseInfoReflection =
// will crash if 'T contains members which aren't only tags
let Construct<'T> (caseInfo: UnionCaseInfo) = FSharpValue.MakeUnion(caseInfo, [||]) :?> 'T
let GetUnionCaseInfoAndInstance<'T> (caseInfo: UnionCaseInfo) = (caseInfo, Construct<'T> caseInfo)
let AllCases<'T> =
FSharpType.GetUnionCases(typeof<'T>)
|> Seq.map GetUnionCaseInfoAndInstance<'T>
#load "SimpleUnionCaseInfoReflection.fs"
type Foos = Foo | Bar | Baz
SimpleUnionCaseInfoReflection.AllCases<Foos> |> Seq.iter (fun (caseInfo, instance) ->printfn "name: %s instance: %O is Bar? : %b" caseInfo.Name instance (instance.Equals(Foos.Bar)))
(*
> name: Foo instance: FSI_0055+Foos is Bar? : false
> name: Bar instance: FSI_0055+Foos is Bar? : true
> name: Baz instance: FSI_0055+Foos is Bar? : false
*)

To slightly extend Robert's example - even if you don't have an instance of the discriminated union, you can use F# reflection to get the information about the type (such as types of the arguments of individual cases). The following extends Robert's sample ans it also prints the types of arguments:
open Microsoft.FSharp.Reflection
let ty = typeof<option<int>>
let cases = FSharpType.GetUnionCases ty
printfn "type %s =" ty.FullName
for case in cases do
printf "| %s" case.Name
let fields = case.GetFields()
if fields.Length > 0 then
printf " of"
for fld in fields do
printf " %s " fld.PropertyType.FullName
printfn ""
For example, for option<int> type, you'll get (I slightly simplified the output):
type Microsoft.FSharp.Core.FSharpOption`1[System.Int32] =
| None
| Some of System.Int32
There are many interesting uses for this information - for example, you could generate DB schema from F# unions or to create functions that will parse XML into a discriminated union (that describes the structure). I talked about the XML processing sample at GOTO conference earlier this year.

It's hard to see how this could possibly work without also having an instance since discrimination unions can carry values.
If you had a type like this for example:
type Status = Success of string | Error of System.Exception | Timeout
What would you except your array to contain for Success or Error in this case?

Related

What are the alternatives to returning a discriminated union from a function?

I'm experimenting with rewriting a complicated piece of code using F#.
For this particular code base, discriminated unions help me a lot, so I'm focusing on using them as much as possible. Specifically, exhaustiveness checks on DUs is helping me avoid lots and lots of bugs.
However, I'm facing a repeating pattern of having to use match ... with to the extent that the clutter in the code is offsetting the benefit I'm getting from exhaustiveness check.
I simplified the pattern I'm dealing with as much as I can and tried to come up with an example that demonstrates the structure of the code I'm writing. The real code base is a lot more complicated and it is in a completely different domain but at the language level, this example represents the issue.
Let's say we want to get some about shoppers based on a classification of shoppers: they're either cat people or dog people. The key thing here is classifying some types (tuples) via DUs.
Here are the domain types:
type PetPerson =
|CatPerson
|DogPerson
type CatFood =
|Chicken
|Fish
type DogFood =
|Burger
|Steak
//some cat food, shopper's age and address
type CatFoodShopper = CatFoodShopper of (CatFood list * int * string)
//some dog food, shopper's age and number of children
type DogFoodShopper = DogFoodShopper of (DogFood list * int * int)
Leaving aside the horrible way we're feeding the poor animals, this domain model needs a function to map PetPerson to CatFoodShopper or DogFoodShopper
At this point, my initial thought is to define a Shopper type, since I cannot return two different types from the following function, based on the results of pattern matching:
type Shopper =
|CatFShopper of CatFoodShopper
|DogFShopper of DogFoodShopper
let ShopperViaPersonality = function
|CatPerson -> CatFShopper (CatFoodShopper ([Chicken;Fish], 32, "Hope St"))
|DogPerson -> DogFShopper (DogFoodShopper ([Burger;Steak], 45, 1))
This solves the problem but then I have lots of places in the code (really a lot) where I end up with a PetPerson and need to get a CatFoodShopper or a DogFoodShopper based on what the PetPerson value is. This leads to unnecessary pattern matching for cases I know I don't have at hand. Here is an example:
let UsePersonality (x:int) (y:PetPerson) =
//x is used in some way etc. etc.
match y with
|CatPerson as c -> //how can I void the following match?
match (ShopperViaPersonality c) with
|CatFShopper (CatFoodShopper (lst,_,_))-> "use lst and return some string "
| _ -> failwith "should not have anything but CatFShopper"
|DogPerson as d -> //same as before. I know I'll get back DogFShopper
match (ShopperViaPersonality d) with
|DogFShopper (DogFoodShopper (lst, _,_)) -> "use lst and return other string"
|_ -> failwith "should not have anything but DogFShopper"
As you can see, I have to write pattern matching code even when I know I'll be getting back a particular value. I have no way of concisely associating the CatPerson value to CatFoodShopper value.
In order to improve things at the call site, I considered using F#'s way of mimicking type classes via interfaces, based on lots of example available here:
type IShopperViaPersonality<'T> =
abstract member ShopperOf: PetPerson -> 'T
let mappingInstanceOf<'T> (inst:IShopperViaPersonality<'T>) p = inst.ShopperOf p
let CatPersonShopper =
{new IShopperViaPersonality<_> with
member this.ShopperOf x =
match x with
|CatPerson -> CatFoodShopper ([Chicken;Fish], 32, "Hope St")
| _ -> failwith "This implementation is only for CatPerson"}
let CatPersonToShopper = mappingInstanceOf CatPersonShopper
let DogPersonShopper =
{new IShopperViaPersonality<_> with
member this.ShopperOf x =
match x with
|DogPerson -> DogFoodShopper ([Burger;Steak], 45, 1)
| _ -> failwith "This implementation is only for DogPerson"}
let DogPersonToShopper = mappingInstanceOf DogPersonShopper
So I no longer have a Shopper type to represent both cat food shoppers and dog food shoppers, but instead an interface defines the mapping from PetPerson values to specific shopper types. I also have individual partially applied functions to make things even easier at the call site.
let UsePersonality1 (x:int) (y:PetPerson) =
match y with
|CatPerson as c ->
let (CatFoodShopper (lst,_,_)) = CatPersonToShopper c
"use lst and return string"
|DogPerson as d ->
let (DogFoodShopper (lst,_,_)) = DogPersonToShopper d
"use lst and return string"
This approach works better when using PetPerson values, but I'm now left with the task of defining these individual functions to keep things clean at the call site.
Note that this example is meant to demonstrate the trade off between using a DU and using an interface to return different types based on the classifying DU parameter, if I may call it that. So don't hang up on my meaningless use of return values etc.
My question is: are there any other ways I can accomplish the semantics of classifying a bunch of tuple (or record) types? If you're thinking active patterns, they're not an option because in the real code base the DUs have more than seven cases, which is the limit for active patterns, in case they would be of help. So do I have any other options to improve on the above approaches?
One obvious way to go about this is to call ShopperViaPersonality before matching PetPerson, not after:
let UsePersonality (x:int) (y:PetPerson) =
//x is used in some way etc. etc.
match ShopperViaPersonality y with
| CatFShopper (CatFoodShopper (lst,_,_))-> "use lst and return some string "
| DogFShopper (DogFoodShopper (lst, _,_)) -> "use lst and return other string"
Also note that if the sole purpose of ShooperViaPersonality is to support pattern matches, you may be better off making it an active pattern:
let (|CatFShopper|DogFShopper|) = function
| CatPerson -> CatFShopper ([Chicken;Fish], 32, "Hope St")
| DogPerson -> DogFShopper ([Burger;Steak], 45, 1)
Then you can use it like this:
let UsePersonality (x:int) (y:PetPerson) =
//x is used in some way etc. etc.
match y with
| CatFShopper (lst,_,_) -> "use lst and return some string "
| DogFShopper (lst, _,_) -> "use lst and return other string"
Logically, an active pattern is pretty much the same as a DU + a function, but on syntactic level, notice how much less nesting there is now.

Slow conversion of F# discriminated union case to string

I have around 100k discriminated union cases I have to convert to strings, but it seems to be extremely slow.
As a comparison, the following executes (in F# interactive) in 3seconds on average :
open System
let buf = Text.StringBuilder()
let s = DateTime.Now
for i in 1 .. 100000 do
Printf.bprintf buf "%A" "OtherFinancingInterest" //string
buf.Length <- 0
printfn "elapsed : %0.2f" (DateTime.Now - s).TotalMilliseconds
While the following executes (also in F# interactive) in over a minute...
open System
let buf = Text.StringBuilder()
let s = DateTime.Now
for i in 1 .. 100000 do
Printf.bprintf buf "%A" OtherFinancingInterest //DU
buf.Length <- 0
printfn "elapsed : %0.2f" (DateTime.Now - s).TotalMilliseconds
The discriminated union has 25 values (the result is still extremely slow, around 16 seconds with two cases, but less so than with 25). Any idea if that is "normal" or if I may be doing something wrong ?
Many thanks
The %A format specifier pretty prints any F# value. It uses reflection to do so. It should only really be used for debugging purposes, and not in normal application code.
Note that using %s in your first example using a string makes it a lot faster because there is no type checking needed at runtime.
For the DU, there is a hack you could use to make the reflection only happen once on application load:
type FinancingInterest =
| OtherFinancingInterest
open FSharp.Reflection
let private OtherFinancingInterestStringMap =
FSharpType.GetUnionCases typeof<FinancingInterest>
|> Array.map (fun c -> FSharpValue.MakeUnion(c, [||]) :?> FinancingInterest)
|> Array.map (fun x -> x, sprintf "%A" x)
|> Map.ofArray
type FinancingInterest with
member this.AsString = OtherFinancingInterestStringMap |> Map.find this
You would also use this with the %s format specifier:
Printf.bprintf buf "%s" OtherFinancingInterest.AsString
I had similar timings to yours in your example, and now this one comes down to 40ms.
This only works as long as all of the DU cases don't have an arguments. You will get an exception on application load as soon as you try anything like this:
type FinancingInterest =
| Foo of string
| OtherFinancingInterest
Having said all this, I think you're better off writing a simple function that explicitly converts your type into a string value, writing out the names in full with repetition if necessary. The names of discriminated union cases should not generally be thought of as data that affects your program. You would usually expect to be able to safely rename case names without affecting runtime behaviour at all.

Is F# aware of its discriminated unions' compiled forms?

A discriminated union in F# is compiled to an abstract class and its options become nested concrete classes.
type DU = A | B
DU is abstract while DU.A and DU.B are concrete.
With ServiceStack, the serialization of types to JSON strings and back can be customized with functions. With respect to the DU type, here's how I could do it in C#.
using ServiceStack.Text;
JsConfig<DU.A>.SerializeFn = v => "A"; // Func<DU.A, String>
JsConfig<DU.B>.SerializeFn = v => "B"; // Func<DU.B, String>
JsConfig<DU>.DeserializeFn = s =>
if s == "A" then DU.NewA() else DU.NewB(); // Func<String, DU>
Is F# aware of its discriminated unions' compiled forms? How would I get the type of DU.A in F# at compile time?
typeof<DU> // compiles
typeof<DU.A> // error FS0039: The type 'A' is not defined
typeof<A> // error FS0039: The type 'A' is not defined
I can easily enough register a function for deserialization in F#.
open System
open ServiceStack.Text
JsConfig<DU>.RawDeserializeFn <-
Func<_, _>(fun s -> printfn "Hooked"; if s = "A" then A else B)
Is it possible to register serialize functions wholly in F# for the concrete types DU.A and DU.B?
Whilst all the behaviour (the abstract classes etc.) is not just an implemenation detail, it is actually defined by the spec, these things are not accesible from F# - this is a quote from the spec
A compiled union type U has:
· One CLI static getter property U.C for each null union case
C. This property gets a singleton object that represents each such
case.
· One CLI nested type U.C for each non-null union case C. This
type has instance properties Item1, Item2.... for each field of the
union case, or a single instance property Item if there is only one
field. However, a compiled union type that has only one case does not
have a nested type. Instead, the union type itself plays the role of
the case type.
· One CLI static method U.NewC for each non-null union case C.
This method constructs an object for that case.
· One CLI instance property U.IsC for each case C. This
property returns true or false for the case.
· One CLI instance property U.Tag for each case C. This
property fetches or computes an integer tag corresponding to the case.
· If U has more than one case, it has one CLI nested type
U.Tags. The U.Tags typecontains one integer literal for each case, in
increasing order starting from zero.
· A compiled union type has the methods that are required to
implement its auto-generated interfaces, in addition to any
user-defined properties or methods.
These methods and properties may not be used directly from F#.
However, these types have user-facing List.Empty, List.Cons,
Option.None, and Option.Some properties and/or methods.
Importantly, "these methods and properties may not be used from F#".
Daniel is correct, you can do this by registering serialization functions for the base type DU. Here is a fuller example
open System
open ServiceStack.Text
type DU = A | B
let serialize = function
| A -> "A"
| B -> "B"
let deserialize = function
| "A" -> A
| "B" -> B
| _ -> failwith "Can't deserialize"
JsConfig<DU>.SerializeFn <- Func<_,_>(serialize)
JsConfig<DU>.DeSerializeFn <- Func<_,_>(deserialize)
let value = [| A; B |]
let text = JsonSerializer.SerializeToString(value)
let newValue = JsonSerializer.DeserializeFromString<DU[]>(text)
Result:
val value : DU [] = [|A; B|]
val text : string = "["A","B"]"
val newValue : DU [] = [|A; B|]
The fact that a DU in F# is a single type is key to its usefulness. The F# approach would be to use pattern matching:
JsConfig<DU>.SerializeFn <- function
| A -> "A"
| B -> "B"
This should work because the union cases are not only nested types in C#, but subtypes as well. Of course if ServiceStack doesn't consider base type serializers then this won't work.

Pattern matching against generic type using 'flexible' type parameter

match value with
| :? list<#SomeType> as l -> l //Is it possible to match any list of a type derived from SomeType?
| _ -> failwith "doesn't match"
As already pointed out, there is no way to do this directly (pattern matching can only bind values, but it cannot bind new type variables). In addition to the (more general) workaround by kvb you can use the fact that all collections implement non-generic IEnumerable, so you can check for this type:
match box value with
| :? System.Collections.IEnumerable as l when
// assumes that the actual type of 'l' is 'List<T>' or some other type
// with single generic type parameter (this is not fully correct, because
// it could be other type too, but we can ignore this for now)
typedefof<SomeType>.IsAssignableFrom
(value.GetType().GetGenericArguments().[0]) ->
l |> Seq.cast<SomeType>
| _ -> failwith "doesn't match"
The code tests whether the value is a non-generic IEnumerable and whether the type parameter is subtype of SomeType. In that case, we got a list of some derived type, so we can cast it to a sequence of SomeType values (this is slightly different than working with list of values of the derived types, but it shouldn't matter for practical purposes).
No, it's unfortunately not possible to do something like this - the CLR doesn't provide any efficient way of doing that kind of type test. See How to cast an object to a list of generic type in F# and F# and pattern matching on generics in a non-generic method implementing an interface for a few (rather ugly) solutions.
I later needed something similar for matching Lazy instances. Here's my solution, in case anyone finds it helpful.
let (|Lazy|_|) (value : obj) =
if box value <> null then
let typ = value.GetType()
if typ.IsGenericType && typ.GetGenericTypeDefinition() = typedefof<Lazy<_>> then
Some(typ.GetGenericArguments().[0])
else None
else None
Usage:
match value with
| Lazy typ when typeof<SomeType>.IsAssignableFrom(typ) -> (value :?> Lazy<_>).Value
| _ -> failwith "not an instance of Lazy<#SomeType>"
According to the F# 2.0 specification, par. 14.5.2 (Solving Subtype Constraints), it will not work, because: "F# generic types do not support covariance or contravariance."
Not the cleanest, but effective:
let matchType<'T> () =
try
let o = Activator.CreateInstance<'T> ()
match box o with
| :? Type1 -> printfn "Type1"
| :? Type2 -> printfn "Type2"
| _ -> failwith "unknown type"
with
| ex -> failwith "%s" (ex.ToString())

How do I customize output of a custom type using printf?

I've read through a good chunk of Expert F# and am working on building an actual application. While debugging, I've grown accustomed to passing fsi commands like this to make things legible in the repl window:
fsi.AddPrinter(fun (x : myType) -> myType.ToString())
I would like to extend this to work with the printf formatter, so I could type e.g.
printf "%A" instanceOfMyType
and control the output for a custom type. The book implies that this can be done (p 93, "Generic structural formatting can be extended to work with any user-defined data types,
a topic covered on the F# website"), but I have failed to find any references as to how to actually accomplish this. Does anyone know how? Is it even possible?
Edit:
I should have included a code sample, it's a record type that I'm dealing with, e.g.
type myType =
{a: int}
override m.ToString() = "hello"
let t = {a=5}
printfn "%A" t
printfn "%A" (box t)
both print statements yield:
{a = 5;}
It looks like the Right Way to do this in F# 2.0 is by using the StructuredFormatDisplay attribute, for example:
[<StructuredFormatDisplay("hello {a}")>]
type myType = {a: int}
In this example, instead of the default {a = 42;}, you would get hello 42.
This works the same way for object, record, and union types. And although the pattern must be of the format "PreText {PropertyName} PostText" (PreText and PostText being optional), this is actually more powerful than ToString() because:
PropertyName can be a property of any type. If it is not a string, then it will also be subject to structured formatting. Don Syme's blog gives an example of recursively formatting a tree in this way.
It may be a calculated property. So you could actually get ToString() to work for record and union types, though in a rather round-about way:
[<StructuredFormatDisplay("{AsString}")>]
type myType =
{a: int}
override m.ToString() = "hello"
member m.AsString = m.ToString() // a property that calls a method
By the way, ToString() will always be used (even for record and union types) if you call printfn "%O" instead of printfn "%A".
Hmm... I vaguely recall some changes to this, but I forget if they happened before or after the CTP (1.9.6.2).
In any case, on the CTP, I see that
type MyType() =
override this.ToString() = "hi"
let x = new MyType()
let xs = Array.create 25 x
printfn "%A" x
printfn "%A" xs
when evaluated in the VFSI window does what I would want, and that
x;;
xs;;
also prints nicely. So, I guess I am unclear how this differs from what is desired?
If you override ToString method, that should do.

Resources