f# - 递归区分联合案例类型

标签 f# ocaml record abstract-syntax-tree discriminated-union

如何创建 OCaml/F# DU 类型,其中它的案例是其他案例的子集?

例如,我想制作一个符号表,其中包含不同的符号声明类型,例如程序类型、变量和函数。

乍一看,我可以看到一个变量包含它的类型,函数也包含一个类型和许多参数变量。所以我想使用 1 DU,而不是分隔到许多记录或别名:

type Symbol =
    | TypeSymbol of id:string
    | VariableSymbol of id:string * type':TypeSymbol
    | FunctionSymbol of id:string * params':VariableSymbol list * type':TypeSymbol

但这是错误的,因为 DU 案例不能是其他案例的子集。如何重新格式化类型以声明 DU 案例相互递归?

最佳答案

对于 F#,最简单的解决方案是创建较小的单例 DU 并引用它们:

type T = T of id:string
type V = V of id:string * type':T
type Symbol =
   | TypeSymbol of T
   | VariableSymbol of V
   | FunctionSymbol of id:string * params': V list * type':T

它通过分解的用法可能是这样的。
let rec print x = 
   match x with
   | TypeSymbol (T typeId) -> 
      typeId

   | VariableSymbol (V (varId, T typeId)) -> 
      sprintf "%s : %s" varId typeId

   | FunctionSymbol (funId, params', T typeId) ->         
      let printedParams = 
         params'
         |> List.map (VariableSymbol >> print) 
         |> String.concat ") -> ("
      sprintf "%s = (%s) -> %s" funId printedParams typeId

关于f# - 递归区分联合案例类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44666981/

相关文章:

f# - 读取 Xml 文件会引发错误 - FAKE F#MAKE

f# - 在列表中查找重复元素的基本功能是什么?

enums - F# 枚举 : expected to have type xxx but here has type xxx

compilation - "failwith"不再被允许?

iphone - 将电压施加到 iPhone 的麦克风端口

f# - 如何运行 websharper 项目?

c++ - 如何使用 Genlex 构建 OCaml 源代码

functional-programming - 如何在 OCaml 中使用列表实现二叉堆?

recursion - 复制递归 F# 记录类型

php - 同一个表上的重复记录并重命名字段值