Reputation: 6442
I have an Option
type:
type Option<'a> =
| Some of value:'a
| None
type MyString = string
// Syntax
type type-name =
| case-identifier1 [of [ fieldname1 : ] type1 [ * [ fieldname2 : ] type2 ...]
| case-identifier2 [of [ fieldname3 : ] type3 [ * [ fieldname4 : ] type4 ...]
...
I want to print something with a format like this:
"type-name: case-identifier(fieldname1:type1:'value1', fieldname2:type2:'value2')"
// Example:
let a : Option<MyString> = Some "1"
print a -> "Option: Some(value:MyString:'1')"
let b = None
print b -> "Option: None"
I've asked a similar question before, but I still can't get the type-name and type of the field.
Upvotes: 1
Views: 127
Reputation: 243096
In your example, you will not be able to print MyString
, because this is a type alias and type aliases do not have any representation in the compiled code (only in some additional F# meta-data, but that does not help here). So, in the compiled code, the runtime just sees string
. I'm going to use a single-case DU instead:
type Option<'a> =
| Some of value:'a
| None
type MyString =
| MyString of string
override x.ToString() = let (MyString s) = x in s
let a = Some (MyString "1")
let b = None
A function that formats the DU values according to your example looks something like this:
open Microsoft.FSharp.Reflection
let formatUnion<'T> (value:'T) =
let case, args = FSharpValue.GetUnionFields(value, typeof<'T>)
let args =
[| for f, v in Seq.zip (case.GetFields()) args ->
sprintf "%s:%s='%O'" f.Name f.PropertyType.Name v |]
sprintf "%s: %s(%s)" (typeof<'T>.Name) case.Name (String.concat "," args)
This prints "Option'1: Some(value:MyString='1')"
- aside from the backtick-one that is there because the type Option
is generic, this looks like the thing you wanted - I did not do anything clever to handle nested types, so that's one thing you'll still need to add.
Upvotes: 3