Choice type implementation in F# - f#

I am fairly new in F# and having some problems with choice type implementation.
I have three types.
type A = p of string
type B = {q:string;r:int}
type C = s of string
Then I've a choice type like this.
type D = A | B | C
Now I am having problems in creating D type of variable. I am trying to do something like this,
let v = {q="abc";r=12}
let vofD = D.B v
But it gives this error,
This value is not a function and cannot be applied
I have tried to search for documentation on this thing and it seems that I'm unable to find any good document or solution on this. Any help will be greatly appreciated.

The problem is that the F# compiler doesn't understand that D.B refers to type B. If you define your discriminated union like this:
type D =
| FromA of A
| FromB of B
| FromC of C
Then you can write let vofD = D.FromB v.

Related

F# pattern matching: how "as" is interpreted when used incorrectly with constructor?

I have a discriminated union with a choice that has another du as its type as follows:
type DunionSubset =
| X
| Y
type Dunion =
| A
| B
| C of DunionSubset
I want to produce a mapping to a list of strings for Dunion type, which naturally extends to C and therefore DunionSubset
When I incorrectly use as to assign an alias to constructor as follows:
let MappingsOfC = function
| X -> ["x"]
| Y -> ["y"]
let StringMappings = function
| A -> ["a";"A"]
| B -> []
| C as c -> (MappingsOfC c)
the compiler gives me:
[FS0019] This constructor is applied to 0 argument(s) but expects 1
How exactly is my incorrect use of as above leading to this compiler error? Interestingly, the location of the compiler error is that of C, not my use of c in MappingsOfC c though Rider ide underlines c and provides a different error.
C as c matches the function argument against the pattern C and also binds it to c. So it's the same as:
let StringMappings c = match c with
| A -> ["a";"A"]
| B -> []
| C -> (MappingsOfC c)
except that this will make c visible in all branches whereas the version with as only makes c visible in the branch that has the as pattern (naturally).
You get an error because C takes an argument, but you're trying to use it without one. If you wrote | A as a ->, | B as b -> and/or | C _ as c, that would work fine.
Actually the left part of -> (before the as and when keywords, if provided) in a matching branch is a pattern. And pattern must be valid - depending on the type of the value provided right after the match keyword.
Here compiler will understand that you are wanting to match a Dunion value because it sees the patterns A and B (which are all valid) first.
Now you can see that C is an invalid pattern for Dunion. The valid pattern here must be: C something
If you don’t care about something (don’t need to use it), still, you must provide a wildcard _ to make the pattern valid: C _
But in your example, I’m pretty sure that you do care, so the code should be like this:
| C c -> MappingsOfC c

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.

Can the F# type system do this?

I have a lot of various types that have a common purpose, but little else in common. For the sake of explanation, they might as well be along the lines of:
type blah<'a> = Blah of 'a
type huha<'a> = Huha of 'a
I often need to repeat a large chunk of boilerplate that could go inside a function along the lines of:
let f (x:something<int>) (g:something<char> -> float) : float =
But that would require somehow enforcing that the two somethings in the type are the same. In other words, I would like to be able to call the function f as:
f (Blah 1) (fun (b:blah<float>) -> .... )
f (Huha 1) (fun (b:huha<float>) -> .... )
Obviously, a trivial solution is to create a discriminated union of all the types function f could possibly take, and make every g (i.e. f's second argument) check it got whatever type it expected. But that means having a massive type that causes the universe to recompile every time anything changes, and it's not like checking types at runtime helps a great deal either.
So, can someone please see a way of doing what I want in a typesafe way? Many thanks.
As far as I understand, you cannot do this directly in F#.
But maybe operator overloading will help. You would have to implement f for every type, though. But maybe you can delegate to a common implementation.
A code example for operator overloading, ensuring the right types:
type T<'a> =
| T of 'a
static member (.+.) (l:T<int>, r:T<char> -> float) = 42.0
type U<'a> =
| U of 'a
static member (.+.) (l:U<int>, r:U<char> -> float) = 13.1
let ft (t:T<char>) = 42.0
let fu (t:U<char>) = 42.0
let t = T 42 .+. ft
let u = U 13 .+. fu
// does not compile:
let wrong = T 42 .+. fu

How to enumerate a discriminated union in 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?

How to implicitly convert to common super types in F# pattern matches?

Problem Summary
At the moment when using f# I must explicitly coerce a value to the parent type of its type in order to get pattern matching expressions to type check correctly. I would ideally like a neater way of doing.
Example
Suppose I have some class hierachy:
type Foo () =
abstract member Value : unit -> string
type A (i:int) =
inherit Foo ()
override this.Value () = i.ToString()
type B (s:string) =
inherit Foo ()
override this.Value () = s
Ideally, and in some programming languages in normally, I would write the equivalent of the following:
let bar (i:int) : Foo =
match i with
| 1 -> B "one"
| _ -> A i
However this fails to type check correctly, giving me the error, "This expression was expected to have type Foo but here has type B". I don't understand why the compiler doesn't have enough information to infer a common super type for the match expression and then check that the common super type is 'Foo'.
At present I am forced to provide an explicit coercion for every case in the pattern match:
let bar2 (i:int) : Foo =
match i with
| 1 -> (B "one") :> Foo
| _ -> (A i) :> Foo
I would like to avoid this.
Further Notes
Intuition suggests that this is a result of a more general issue. I would have thought though that something as common as pattern matching, or if statements which also exhibit the same property, would have a type checking rule to account for common super types.
Before anyone suggests - I appreciate that if A or B were Object Expressions this would work, but my real example is creating instances of C# classes where they are normal classes.
Is there a way for me to declare functions to implicitly convert types, as for example scala has, so I could apply automatic conversions for the module where I'm doing this generation?
Thanks for any help on this matter.
I would use upcast, a la
[<AbstractClass>]
type Foo () =
abstract member Value : unit -> string
type A (i:int) =
inherit Foo ()
override this.Value () = i.ToString()
type B (s) =
inherit Foo ()
override this.Value () = s
let bar2 i : Foo =
match i with
| 1 -> upcast B "one"
| _ -> upcast A i
You still have to add it to every branch, but this is often preferable to casting to the type, since often the typename is like 20 or 30 characters long (MyNamespace.ThisThingy), whereas upcast is just 6 characters.
But, briefly, the language rules don't allow for anything else, the types of all the branches have to be equal.
I've seen this question a couple of times before, but I just realized that there is quite an interesting way to workaround the issue (without any significant negative effects such as big runtime overhead).
You can use a very simple computation expression that has only Return member. The builder will have a type parameter and Return will expect values of this type. The trick is, that F# does insert automatic upcasts when calling a member. Here is the declaration:
type ExprBuilder<'T>() =
member x.Return(v:'T) = v
let expr<'T> = ExprBuilder<'T>()
To write a simple pattern matching that returns anything as obj, you can now write:
let foo a = expr<obj> {
match a with
| 0 -> return System.Random()
| _ -> return "Hello" }
You still have to be explicit about the return type (when creating the computation expression), but I find the syntax quite neat (but it is definitely a tricky use that could confuse people who'll see it for the first time).

Resources