繁体   English   中英

相当印刷的工会

[英]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是通用的,这看起来像你想要的东西 - 我没有做任何聪明的事情处理嵌套类型,这是你还需要添加的一件事。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM