2

我似乎无法在 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)))
}
4

1 回答 1

3

如果您唯一反对的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>在预期有限流的上下文中使用 a 。换句话说,在stream0<'a> 和stream0<'a> 的有限版本之间有许多潜在的相等性。

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

let app_once  = {x;next} => next(())

无法使用该类型

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

在实践中,递归类型stream0<'a>及其许多类型等式比有用更麻烦,并且默认情况下禁用此类递归类型。

于 2021-01-13T07:13:25.930 回答