【问题标题】:SML - bidirectional infinite and finite sequence interleavingSML - 双向无限和有限序列交织
【发布时间】:2017-05-30 08:46:54
【问题描述】:

我有下一个数据类型和函数的声明:

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

下一个函数是我编写的,用于交错两个这样的序列: 如果第一个序列是... ,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

我应该对代码进行哪些更改,这将是函数的行为?

【问题讨论】:

    标签: sequence sml smlnj sequences seq


    【解决方案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。 《Learn You a Haskell》这本书有一个chapter on tree zippers,可能值得一读。在本章的术语中,您可能需要一个返回“面包屑轨迹”的函数。列表拉链在概念上更简单一些,但带有 'a bseqs 的懒惰,语法上并非如此。

    【讨论】:

      猜你喜欢
      • 2011-08-30
      • 2013-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 2014-07-19
      相关资源
      最近更新 更多