【问题标题】:How to concisely unwrap an algebraic data type in OCaml?如何在 OCaml 中简洁地解开代数数据类型?
【发布时间】:2018-08-16 22:38:16
【问题描述】:

有没有一种在 OCaml 中简洁地展开代数数据类型的好方法?例如,考虑以下代码,它定义了两种不同类型的数学函数

type ftype =                                                         
    | Quadratic of {alpha : float; a : float array; aa : float array}
    | General of {eval : float array->float}
type myfn = {                                                                   
    nvar : int;
    typ : ftype}  
let f = {                                                                       
    nvar = 2;                                                                   
    typ = General {eval = fun x-> x.(0) +. x.(1)}} 

出于调试目的,有时只评估一个函数或在顶层检查它的值会很好。但是,如果我们想要计算 f,我们需要一个看起来像

的代码
let x = [| 1.; 2. |]
let y = match f.typ with General(f) -> f.eval(x)

这有点难看,而且打字很痛苦,尤其是在分层很深的情况下。我想定义某种语法,例如

let y = f.typ.General.eval(x)

而且,是的,代码不安全,无法编译。也就是说,接近这个的东西对于调试目的来说是很好的,这样我们就不必编写一段冗长的代码来解包一个值。有什么好的方法可以做到这一点吗?

【问题讨论】:

  • 您可以使用 let 绑定进行解构:let y = let { typ = General(f) } = f in f.eval(x)。可以说不那么难看,但在这种情况下肯定不会更短。然而,它会更好地处理嵌套。

标签: ocaml algebraic-data-types


【解决方案1】:

如果只是为了调试目的,你总是可以这样写:

let { typ = General { eval; } ; } = f in
let y = eval x in
...

当然,编译器会打印一个警告 8(非详尽的模式匹配)。

我认为你不能做得更简洁,总和类型意味着可读和安全。不快,抱歉。

【讨论】:

    【解决方案2】:

    当您在顶层使用代码时,使用可反驳(即不完整)模式是完全可以的,例如,

    let [1;3;5] = List.filter is_odd [1;2;3;4;5]
    

    为了防止顶级警告破坏您的体验,只需使用

    禁用它们
    #warnings "-P";;
    

    (或“-8”,也一样,不要忘记输入前导#,它是指令的一部分,而不是提示符)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      • 1970-01-01
      • 1970-01-01
      • 2018-07-15
      相关资源
      最近更新 更多