F#中带and与Lazy的递归类型定义及自定义值类型不符问题咨询
类型定义的作用
这组类型是F#中实现惰性流的经典定义,核心是利用惰性求值实现按需生成的序列,可支持无限长度的序列场景:
StreamCell<'a>是流的节点联合类型,包含两种情况:Nill:表示流已到末尾,无后续元素Cons:表示当前节点存在一个'a类型的元素,以及后续的Stream<'a>类型流
Stream<'a>是Lazy<StreamCell<'a>>的类型别名,意味着所有流节点的计算都是惰性的,只有实际访问时才会生成节点值,不会预先生成全量数据,非常适合实现斐波那契序列、无限自然数序列这类不需要提前加载所有元素的场景。
代码错误原因
你代码的核心问题是混淆了F#原生列表的构造逻辑和自定义Stream类型的构造逻辑:
- 你使用的
::是F#原生list<'a>类型的专属构造运算符,和你自定义的StreamCell的Cons用例没有任何关联,::的左操作数是列表元素,右操作数必须是同类型的列表,只要用到::编译器就会默认你在构造原生列表,自然不会得到你预期的Stream/StreamCell类型。 Stream<'a>要求Lazy包裹的内容必须是StreamCell<'a>类型的值,你代码中Lazy包裹的都是原生列表构造表达式,不符合类型约束。
以构造包含1、2两个元素的Stream<int>为例,正确写法如下:
// 末尾Nill节点,Lazy包裹后就是Stream<int>类型 let streamTail = Lazy(Nill) // Cons第二个参数必须是Stream<'a>类型,外层再包Lazy let stream1 = Lazy(Cons(2, streamTail)) // 最终的流对象 let intStream = Lazy(Cons(1, stream1))
如果希望获得类似原生列表的简洁构造体验,可以自定义运算符:
// 自定义Stream构造运算符 let (::%) elem nextStream = Lazy(Cons(elem, nextStream)) // 简化构造写法 let intStream2 = 1 ::% 2 ::% Lazy(Nill)
内容的提问来源于stack exchange,提问作者ca9163d9
相关产品推荐
相关产品推荐

