3

在论文Streams à la carte: Extensible Pipelines with Object AlgebrasBiboudis 等人。概述使用对象代数“模拟类型构造器多态性”的方法。

我正在尝试使用此方法在 F# 中实现一个高阶示例,类似于 中描述的示例,Typed Tagless Final Interpreters并具有以下内容:

type App<'f,'a> = interface end

type ExprSYM<'f,'a> = 
  abstract litInt: int -> App<'f,int>
  abstract litBool : bool -> App<'f,bool>
  abstract add : App<'f,int> -> App<'f,int> -> App<'f,int>
  abstract gt : App<'f,int> -> App<'f,int> -> App<'f,bool>
  abstract conj : App<'f,bool> -> App<'f,bool> -> App<'f,bool>

相关部分Brand Freshness描述了在类型构造函数中嵌套类。我对 F# 的翻译如下:

type Eval<'a> =
  static member t = new obj()
  static member prj (app : App<Eval.t,'a>) = app :> Eval<'a>
  inherit App<Eval.t,'a>

但是,我得到了错误The type 't' is not defined

在 F# 中写这个的正确方法是什么?

4

1 回答 1

2

使用嵌套类并不会特别给您带来任何好处。正如作者所说

在 OCaml 的 Yallop 和 White 技术中,这在语法上是由品牌的“新鲜度”来确保的t,它是类型构造函数私有的。在 Java 中,该属性是由约定保证的:每个子类型S都有App一个本地定义的品牌,并且除了存在之外t没有子类型。App<S.t, X>S

因此您可以在 F# 中使用不同的约定(不支持接口中的嵌套类或静态成员)获得相同的结果。例如,您可以在模块内创建子类和单独的标记类:

module Pull = 
    type t = class end
    type Pull<'t> = 
        inherit App<t, 't>
    let prj (app : App<t, 't>) = app :?> Pull<'t>

然后确保您不会Pull.t在其他地方使用。

于 2015-08-10T16:49:22.513 回答