ocaml - OCaml 多态递归错误
问题描述
给定以下类型:
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
}
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)}
我从编译器得到一个错误:
错误:此表达式具有类型 b#1 堆栈,但预期的表达式类型为 'a 堆栈类型构造函数 b#1 将逃脱其范围
在这行代码中:
| 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
需要一段时间才能做到这一点,而不会遇到通过使用一些帮助类型不可避免地纠正的晦涩错误消息,但我似乎无法弄清楚如何使用助手纠正这个问题,或者我是否正在尝试对我的类型做一些愚蠢的事情。
消除此错误的正确方法是什么?
解决方案
我认为这些功能有些不连贯。添加一些注释并删除不相关的分支给出:
let rec loop (type s) (proc : s process) =
match proc.root with
| Success value ->
let rec step (type t) (x : t stack) =
match x with
| NoStack -> ()
| AndThenStack (callback, rest) ->
loop {proc with root = callback value; stack = rest }
(*^^^^^*)
| OnErrorStack (callback, rest) -> step rest
in
step proc.stack
| _ -> ()
其中“带下划线”的变量是错误消息的主题:
错误:此表达式的类型为 s,但预期的表达式为 t 类型
如果第一次通过step
对 an进行操作(OnErrorStack : unit stack)
,然后第二次通过step
对 an进行操作,会发生(AndThenStack : int stack)
什么?
换句话说,如果 to 的参数loop
类似于:
{ root = Success ();
stack = OnErrorStack ((fun () -> Success 3),
AndThenStack ((fun x -> Success (float_of_int x)),
(NoStack : float stack))) }
虽然(value : unit)
将与 first 兼容step
,但在我看来,没有什么能保证它与 second 的兼容性step
,而是作用于OnErrorStack
(int
在反例中) 中存在类型的值。
推荐阅读
- ansible - 如何在ansible中用“-”分隔单词
- php - 仅通过 FTP 从 FTP 服务器获取当前日期的文件
- javascript - 如何检查四个数组的长度是否相同?角打字稿
- google-maps - 在 React-Native-Maps 中:您可以更新特定的标记而不必重新渲染所有标记吗?
- aws-lambda - EventBridge 与 API 网关
- javascript - 使用 JavaScript 向元素添加内容样式
- for-loop - Julia中N xd矩阵的通用嵌套for循环
- matlab - 将 y'(x)^2 作为微分方程输出的 Matlab 程序
- python - 如何解决 TypeError:无法为
带类型列表 - python - 同时处理 2 个递归调用