漂亮的印刷歧视工会
Pretty print discriminated unions
我有一个 Option
类型:
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 ...]
...
我想用这样的格式打印一些东西:
"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"
我之前问过一个,但我仍然无法获取字段的类型名称和类型。
在您的示例中,您将无法打印 MyString
,因为这是一个类型别名,并且类型别名在编译代码中没有任何表示(仅在一些额外的 F# 元数据中,但这在这里没有帮助)。因此,在编译代码中,运行时只看到 string
。我将改用单例 DU:
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
根据您的示例格式化 DU 值的函数如下所示:
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)
这会打印 "Option'1: Some(value:MyString='1')"
- 除了因为类型 Option
是泛型而存在的反引号之外,这看起来像你想要的东西 - 我没有做任何聪明的事情来处理嵌套类型,所以这是您仍然需要添加的一件事。
我有一个 Option
类型:
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 ...]
...
我想用这样的格式打印一些东西:
"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"
我之前问过一个
在您的示例中,您将无法打印 MyString
,因为这是一个类型别名,并且类型别名在编译代码中没有任何表示(仅在一些额外的 F# 元数据中,但这在这里没有帮助)。因此,在编译代码中,运行时只看到 string
。我将改用单例 DU:
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
根据您的示例格式化 DU 值的函数如下所示:
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)
这会打印 "Option'1: Some(value:MyString='1')"
- 除了因为类型 Option
是泛型而存在的反引号之外,这看起来像你想要的东西 - 我没有做任何聪明的事情来处理嵌套类型,所以这是您仍然需要添加的一件事。