从构造函数中进行通用提取

1 f# pattern-matching

在F#和OCaml中,我最终写了很多代码

type C = Blah of Whatever  
let d = Blah (createWhatever ())  // so d is type C  
...  
let x = match d with | Blah b -> b
Run Code Online (Sandbox Code Playgroud)

我想要的是这个

...  
let x = peel d
Run Code Online (Sandbox Code Playgroud)

剥离适用于任何构造函数/鉴别器.
当然,我不是唯一一个对此感到恼火的人.
编辑:很好的答案,但我没有代表对他们投票.这种情况怎么样?

member self.Length = match self with | L lab -> lab.Length
Run Code Online (Sandbox Code Playgroud)

gas*_*che 5

不可能安全地做到这一点:如果peel是一个函数,它的类型是什么?它不能打字,因此不能成为语言中的"好人".

你可以 :

  • 使用反射(在F#中)或类型破坏函数(在OCaml中它是Obj模块),但你会得到一些不安全的东西,不精确的类型,所以它相当丑陋,"使用风险自负"

  • 使用元编程为您生成peel每种类型的不同版本.例如,使用type-conv OCaml工具,您可能隐式type blah = Blah of something定义了一个函数peel_blah,并type foo = Foo of something定义了peel_foo.

更好的解决方案是......首先不需要这样的解决方案peel.我看到两种可能性:

  • 您可以使用聪明的模式而不是函数:通过使用let (Blah whatever) = f x,或者fun (Blah whatever) -> ...,您不再需要解包功能.

  • 或者你可以,而不是写type blah = Blah of what,写

    type blah = (blah_tag * whatever) and blah_tag = Blah

    这样,你就没有总和类型而是产品类型(你写的(Blah, whatever)),而你peel就是这样snd.你还有一个不同(不兼容)键入每个blah,foo等等,但一个统一的访问接口.