我有下一个数据类型和函数声明:
datatype direction = Back | Forward
datatype 'a bseq = bNil | bCons of 'a * (direction -> 'a bseq)
fun bHead (bCons (x, _)) = x
| bHead bNil = raise EmptySeq
fun bForward(bCons(_, xf)) = xf Forward
| bForward bNil = raise EmptySeq
fun bBack (bCons (_, xf)) = xf Back
| bBack bNil = raise EmptySeq
fun intbseq k =
let fun go Forward = intbseq (k+1)
| go Back = intbseq (k-1)
in bCons (k, go) end
下一个函数由我编写,用于交错两个序列:
如果第一个seq是... ,1,2,3,4,5, .....
而第二个是...,5,6,7,8,9,...
他们交错的新序列是:
... ,3,-1,4,0,5,1,6,2,7,3, ......
代码:
fun binterleaving_aux _ bNil yq = yq
| binterleaving_aux _ xq bNil = xq
| binterleaving_aux firstb (bCons(x,xf)) (bCons(y,yf)) =
bCons(x, fn dir =>
if dir = Forward
then binterleaving_aux true (bCons (y, yf)) (xf dir)
else if firstb
then binterleaving_aux false (yf dir) (xf dir)
else binterleaving_aux false (bCons (y,yf)) (xf dir)));
fun binterleaving bseq1 bseq2 = binterleaving_aux true bseq1 bseq2;
对于那个例子:
binterleaving (intbseq 5) (intbseq 1);
bForward(it);
bForward(it);
bForward(it);
bForward(it);
bBack(it);
bBack(it);
bBack(it);
bBack(it);
它适用于2个无限序列。
问题是至少其中一个是有限的。
例如,如果我这样做:
binterleaving (bCons(10, fn dir => bCons((9, fn dir => bNil)))) (intbseq 5);
bForward(it);
bForward(it);
bForward(it);
bForward(it);
bBack(it);
bBack(it);
bBack(it);
bBack(it);
如果我回去,我会失去10和9,而如果我先回去,则相反,当我向前迈进时,我失去了他们。
结果是按照呼叫的顺序:
val it = bCons (10,fn) : int bseq
val it = bCons (5,fn) : int bseq
val it = bCons (9,fn) : int bseq
val it = bCons (6,fn) : int bseq
val it = bCons (7,fn) : int bseq
val it = bCons (6,fn) : int bseq
val it = bCons (5,fn) : int bseq
val it = bCons (4,fn) : int bseq
val it = bCons (3,fn) : int bseq
正确的结果应该是:
val it = bCons (10,fn) : int bseq
val it = bCons (5,fn) : int bseq
val it = bCons (9,fn) : int bseq
val it = bCons (6,fn) : int bseq
val it = bCons (7,fn) : int bseq
val it = bCons (6,fn) : int bseq
val it = bCons (9,fn) : int bseq
val it = bCons (5,fn) : int bseq
val it = bCons (10,fn) : int bseq
我应该做的代码有哪些变化,这将是函数的行为?
答案 0 :(得分:1)
问题是至少其中一个是有限的。
binterleaving (bCons(10, fn dir => bCons((9, fn dir => bNil)))) (intbseq 0)
当你的有限序列减少到bNil
时,它应该如何回到原始值?将有限序列与无限序列交织的语义似乎有点不明确。
也就是说,当有限的一个结束并且无限的一个继续时,沿着无限序列存储的参考在哪里,有限的那个以相反的方式再次开始?
采取上面的例子并评估它几步(原谅我的懒惰记法):
binterleaving (bCons(10, fn dir => bCons((9, fn dir => bNil)))) (intbseq 0)
⇒ binterleaving (bCons(10, fn dir => bCons((9, fn dir => bNil))))
(bCons( 0, fn dir => ...intbseq (+/- 1)...))
⇒ binterleaving_aux true (bCons(10, fn dir => bCons((9, fn dir => bNil))))
(bCons( 0, fn dir => ...intbseq (+/- 1)...))
⇒ bCons (9, fn dir =>
if dir = Forward
then binterleaving_aux true (bCons (0, fn dir => ...intbseq (+/- 1)...))
((fn dir => bNil) dir)
else ...)
通过将Forward
应用于最外层的fn
来评估一次,可以得到:
bCons (9, (fn dir => ...) Forward)
⇒ bCons (9, binterleaving_aux true (bCons (0, fn dir => ...intbseq (+/- 1)...))
((fn dir => bNil) dir))
⇒ bCons (9, binterleaving_aux true (bCons (0, fn dir => ...intbseq (+/- 1)...)) bNil)
⇒ bCons (9, bCons (0, fn dir => ...intbseq (+/- 1)...))
此时,在任何能够后退的函数中都没有有限序列9的踪迹。仅在binterleaving
的初始返回值。
修复主要在于binterleaving
的基本情况,它抛弃了有限序列。相反,将空序列与非空序列交错的结果应该是非空序列,当反转时,返回空序列之前它为空(这可能也是空的) ,但可能是非空的。)
您可以在列表中将双向序列视为惰性zipper。 “了解你是一个Haskell”这本书的chapter on tree zippers可能值得一读。在本章的术语中,您可能需要一个返回" breadcrumb trail"的函数。列表拉链在概念上有点简单,但是散布着' bseq 的懒惰,在语法上并非如此。