有人可以解释一下这个 OCaml 程序中使用的类型语法吗?

2024-05-04

以下类型取自这个问题 https://stackoverflow.com/q/50586942/633183

(* contains an error, later fixed by the OP *)
type _ task =
| Success : 'a -> 'a task
| Fail : 'a -> 'a task
| Binding : (('a task -> unit) -> unit) -> 'a task
| AndThen : ('a -> 'b task) * 'a task -> 'b task
| OnError : ('a -> 'b task) * 'a task -> 'b task

type _ stack =
| NoStack : 'a stack
| AndThenStack : ('a -> 'b task) * 'b stack -> 'a stack
| OnErrorStack : ('a -> 'b task) * 'b stack -> 'a stack

type 'a process = 
{ root: 'a task 
; stack: 'a stack 
}

我对 OCaml 比较陌生,但我从未见过:语法与之前一样使用。例如,我见过这样定义的多态类型,使用of syntax

type 'a expr =
    | Base  of 'a
    | Const of bool
    | And   of 'a expr list
    | Or    of 'a expr list
    | Not   of 'a expr

在最初的问题中,我不清楚这些变体是如何构造的,因为看起来每个变体都不接受参数。以这个简化的例子为例

type 'a stack =
  | Foo : int stack
  | Bar : string stack
;;
type 'a stack = Foo : int stack | Bar : string stack

尝试制作一个int stack using Foo

Foo 5;;
Error: The constructor Foo expects 0 argument(s),
       but is applied here to 1 argument(s)

然而,无需争论

Foo;;
- : int stack = Foo

好的,但是在哪里int?如何存储这种类型的数据?

在下面的OP程序中,他/她“正常”匹配类型,例如Success value -> ... or Fail value -> ...。同样,如果变体构造函数不接受参数,如何构造该值?

let rec loop : 'a. 'a process -> unit = fun proc ->
match proc.root with
| Success value -> 
    let rec step = function
    | NoStack -> ()
    | AndThenStack (callback, rest) -> loop {proc with root = callback value; stack = rest }
    | OnErrorStack (_callback, rest) -> step rest  <-- ERROR HERE
    in
    step proc.stack
| Fail value -> 
    let rec step = function
    | NoStack -> ()
    | AndThenStack (_callback, rest) -> step rest
    | OnErrorStack (callback, rest) -> loop {proc with root = callback value; stack = rest }
    in
    step proc.stack
| Binding callback -> callback (fun task -> loop {proc with root = task} )
| AndThen (callback, task) -> loop {root = task; stack = AndThenStack (callback, proc.stack)}
| OnError (callback, task) -> loop {root = task; stack = OnErrorStack (callback, proc.stack)}

有人可以帮助我填补我的知识空白吗?


这些类型是广义代数数据类型。也称为GADTs http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec251。 GADT 使得细化构造函数和类型之间的关系成为可能。

在您的示例中,GADT 被用作引入存在量化类型的一种方式:删除不相关的构造函数,可以编写

type 'a task =
| Done of 'a
| AndThen : ('a -> 'b task) * 'a task -> 'b task

Here, AndThen是一个带有两个参数的构造函数:类型的回调'a -> 'b task and a 'a task并返回一个类型的任务'b task。这个定义的一个显着特征是类型变量'a只出现在构造函数的参数中。一个自然的问题是我是否有价值AndThen(f,t): 'a task,什么类型f?

答案是,类型f部分未知,我只知道有一种类型ty使得两者f: ty -> 'a task and t: ty。但此时所有信息都超出了单纯存在的范围ty已丢失。由于这个原因,类型ty称为存在量化类型。

但在这里,这个小信息仍然足以有意义地操纵这样的值。我可以定义一个函数步骤

let rec step: type a. a task -> a task = function
| Done _ as x -> x
| AndThen(f,Done x) -> f x
| AndThen(f, t) -> AndThen(f, step t)

尝试应用该功能f在构造函数中AndThen如果可能的话, 使用构造函数之外的信息AndThen始终存储兼容的回调和任务对。

例如

let x: int task = Done 0
let f: int -> float task =  fun x -> Done (float_of_int (x + 1))
let y: float task = AndThen(f,x)
;; step y = Done 1.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有人可以解释一下这个 OCaml 程序中使用的类型语法吗? 的相关文章

  • 将 OCaml 转换为 F#:将 OCaml open_box 和 close_box 转换为 F#

    我正在将几个基于 OCaml 的模块转换为 F 并遇到了 OCaml 打印格式化函数open box 和 close box http caml inria fr pub docs manual ocaml libref Format ht
  • 修复区域设置扩展中的类型变量

    鉴于此代码 locale A fixes foo a locale B A fixes bar a a locale C A fixes baz a begin sublocale B foo foo baz end I get Type
  • Fortran 指针多态性

    我正在尝试使用指针在对象之间创建链接 使用 Fortran 下面是代码片段 module base pars module type abstract public base pars end type end module module
  • 如何返回派生类型?

    我有一个 Validator 类及其派生类 当我尝试返回指向派生类的指针时 方法返回基类 验证器 而不是派生类 class Validator public std string m name BaseValidator static co
  • 编译器错误:对调用的引用不明确

    Case 1 static void call Integer i System out println hi i static void call int i System out println hello i public stati
  • 将对象从一个派生类更改为另一个派生类

    我有几个类共享一个公共基类 除了它们的方法工作方式不同之外 因此 在下面的示例中 加法器和乘法器除了执行计算的方式不同之外都是相同的 有没有办法即时将 a 更改为乘数 我是否需要实现派生类之间相互转换的方法 例如就像是 a a asMult
  • 使用只有一个元组值的变体类型构造函数

    type foo Foo of int int let t 1 2 Foo t Error The constructor Foo expects 2 argument s but is applied here to 1 argument
  • 如何使用 opam 安装特定版本的 ocaml 编译器

    如何使用 opam 或其他包管理器 安装特定版本的 ocaml 编译器 和兼容包 我快速浏览了 opam 文档 但没有找到相关信息 我需要 ocaml 编译器 最好是本机代码编译器 来构建 unison 一个文件同步软件 我需要使用相同版本
  • 多态性和数组指针[重复]

    这个问题在这里已经有答案了 我有一个A类 class A public virtual double getValue 0 还有B类 class B public A public virtual double getValue retur
  • OCaml 中的线性类型

    Rust http www rust lang org 有一个线性类型系统 有什么 好的 方法可以在 OCaml 中模拟这个吗 例如 当使用 ocaml lua 时 我想确保仅当 Lua 处于特定状态 堆栈顶部的表等 时才调用某些函数 Ed
  • 如何在 OCaml 中使协变可观察

    我正在尝试为值制作一个包装器 允许调用者自行注册以获取有关它的通知 这是一些 工作 代码 module Thing sig type a t val make a gt a t val watch a gt unit gt a t gt u
  • 有人可以解释一下这个 OCaml 程序中使用的类型语法吗?

    以下类型取自这个问题 https stackoverflow com q 50586942 633183 contains an error later fixed by the OP type task Success a gt a ta
  • 使用 ocaml List.fold_left 列表中的最后一个元素

    我可以通过以下代码找到列表的最后一个元素 let last xs a list a let rec aux xs prev match xs with gt prev x ys gt aux ys x in match xs with gt
  • Java中的引用变量到底是什么?它与其他变量有何不同?

    我一直在研究 Java 中的继承 作者声明 被引用的对象类型 而不是引用变量的类型 决定了将执行哪个版本的重写方法 这种说法非常令人困惑 这本书所指的是多态性 更具体地通过动态调度 简而言之 想象一下以下类 public class Per
  • OCaml 文字负数?

    我在学 这是我觉得奇怪的事情 let test treeways x match x with when x lt 0 gt 1 when x gt 0 gt 1 gt 0 如果我这样称呼它 test threeways 10 我会得到类型
  • Ocaml 模块和包的区别

    我基本上是在尝试遵循这篇文章中的 stackoverflow 答案 OCaml 中 HttpRequest 的最佳模块是什么 https stackoverflow com questions 14134116 what is the be
  • 从父类调用子类方法

    a doStuff 方法是否可以在不编辑 A 类的情况下打印 B did stuff 如果是这样 我该怎么做 class Program static void Main string args A a new A B b new B a
  • 调用基本方法而不是覆盖方法

    在 C 中 类A包含一个公共方法Foo 它进行一些处理并返回一个值 protected method Bar 也在课堂上A执行与以下相同的逻辑Foo 然后进行一些额外的处理 然后返回一个值 为了避免重复代码 Bar calls Foo 并使
  • 为什么在 OCaml 中更喜欢柯里化而不是元组参数?

    Caml简介 http www cs jhu edu scott pl lectures caml intro html says 请注意 在 Caml 中 最好对多参数函数使用柯里化函数定义 而不是元组 比较时 a gt b gt c调用
  • 为什么计算斐波那契数需要很长时间?

    几天前我开始学习Ocaml 我尝试编写一个斐波那契数字程序 let rec fib a if a 1 a 2 then 1 else fib a 1 fib a 2 该代码不是最佳的 因为我不知道如何处理异常情况 但现在 如果我尝试计算 f

随机推荐