这是我的问题的简化版本。
我有一个递归数据结构(Stream1)。当我介绍幻像类型(流a)时,递归描述(即t1)不再有效。另一方面,t2通过创建无限结构而工作正常,因为它直接使用Stream1。我需要使用构造函数preI,例如在t1中。我错过了什么?我需要t1表现得像t2 - 也就是说,返回一个无限的流。
data Stream a = Stream Stream1
deriving (Eq, Show)
data Stream1 = PreI Integer Stream1
deriving (Eq, Show)
preI :: Integer -> Stream Int -> Stream Int
preI n (Stream s) = Stream (PreI n s)
t1 :: Stream Int
t1 = let x = preI 0 x
in x
t2 :: Stream Int
t2 = let x = PreI 0 x
in Stream x
答案 0 :(得分:6)
preI :: Integer -> Stream Int -> Stream Int
preI n (Stream s) = ...
-- ^^^^^^^^^^
此模式匹配在生成任何输出之前强制参数。对于流,这很糟糕,因为它将最不固定的点保持在底部(非终止)而不是无限流。
您可以尝试使用lazy / irrefutable模式匹配:
preI :: Integer -> Stream Int -> Stream Int
preI n ~(Stream s) = Stream (PreI n s)
-- ^
这实质上意味着:
preI :: Integer -> Stream Int -> Stream Int
preI n z = Stream (PreI n s)
where s = case z of Stream x -> x
首先在输出中生成Stream, PreI
,然后才开始展开其输入(在使用s
时发生)。
或者,更好的是,将Stream
从data
更改为newtype
:这样,模式匹配将始终是懒惰的。实际上,使用newtype
我们在运行时不再有任何包装,模式匹配实际上是无操作。