ReScript 中的无限列表/流

Infinite Lists / Streams in ReScript

我似乎无法在 ReScript 中找到无限列表的正确键入。

我第一次尝试:

type rec stream<'a> = ('a, () => ('a, stream<'a>))

这是不正确的,因为 ReScript 认为该类型是循环的。所以我尝试了:

type rec stream<'a> = ('a, Lazy.t<() => ('a, stream<'a>)>)

这仍然给我一个类型错误。

最终我试图让这段代码工作,但由于类型签名是无限的而失败了。

let rec from: (int, Lazy.t<() => (int, Lazy.t<...>) = (x: int) => {
    (x, () => Lazy.from_fun(from(x+1)))
}

如果您唯一反对 Sequence 的是 Nil 情况,您可以定义

type rec stream<'a> = { x:'a, next:() => stream<'a> }

与您的定义不同的是,我们正在创建一个新的递归类型,而不是试图定义一个递归类型表达式。

编辑:

使用元组或记录的区别在于元组是结构类型的,而记录是名义类型的。

这改变了平等和身份方面的一切。

特别是原始定义可以读作

type stream0<'a> = ('a, () => 'b ) as 'b

那么每当想要比较一个类型 stream0<'a> 和一个元组类型时,可能需要无限次地扩展这个缩写。

例如,这个函数类型正确。

let f: stream0<int> => (int, ()=>(int,() => _)) = (x) => x

或这个:

let app_once = ((x,next)) => next ()

这里的一个重要结果是可以在预期有限流的上下文中使用 stream0<'a>。 换句话说,在 stream0<'a> 和 stream0<'a> 的有限版本之间有许多潜在的相等性。

相反,stream<'a> 的记录定义创建了一个新的不同类型构造函数 stream。因此,stream<'a> 只能等于 stream<'a>。换句话说,为 stream<'a>

设计的函数
let app_once  = {x;next} => next(())

无法使用类型

type one_stream<'a> = { x:'a, next:() => ('a, ()) }

在实践中,stream0<'a> 的递归类型和它的许多类型等式是麻烦多于有用,并且这种递归类型在默认情况下是禁用的。