具有惰性列表功能的SML

时间:2018-04-02 09:17:43

标签: sml lazylist

我试图创建一个可以返回lazylist的特定第n个元素的函数。

这是我做的:

datatype 'a lazyList = nullList
                 | cons of 'a * (unit -> 'a lazyList)

fun Nth(lazyListVal, n) = (* lazyList * int -> 'a option *)
    let fun iterator (laztListVal, cur, target) =
        case lazyListVal of
             nullList => NONE
           | cons(value, tail) => if cur = target
                                  then SOME value
                                  else iterator (tail(), cur+1, target)
    in
        iterator(lazyListVal,1,n)
    end

我预计结果是,当重复进行时,变量 cur 最终与变量 target 相同,然后是函数迭代器返回 SOME value ,以便返回最后的第n个元素。

但是当我编译并运行时,它只返回第一个元素,但是我使用lazylist对象进行测试。

请说明问题是什么。我不知道......

cf)我创建了另一个与此问题相关的函数,即将lazylist转换为包含前N个值的SML原始列表的函数。上面的代码:

fun firstN (lazyListVal, n) = (* lazyList * int -> 'a list *)
    let fun iterator (lazyListVal, cur, last) =
        case lazyListVal of
             nullList => []
           | cons(value, tail) => if cur = last
                                  then []
                                  else value::iterator(tail(),cur+1,last)
    in
        iterator(lazyListVal,0,n)
    end          

奇怪的是函数firstN正常工作。

1 个答案:

答案 0 :(得分:0)

问题是您的iterator函数确实case lazyListVal of ...,但递归尾部称为 laztListVal ,因此对于每次迭代,它都会一直查看第一个清单。使用更好的变量名来避免这种"隐形"错误。

有关nth的更简单定义:

datatype 'a lazyList = NullList | Cons of 'a * (unit -> 'a lazyList)

fun nth (NullList, _) = NONE
  | nth (Cons (x, xs), 0) = SOME x
  | nth (Cons (_, xs), n) = nth (xs (), n-1)

val nats = let fun nat n = Cons (n, fn () => nat (n+1)) in nat 0 end

val ten = nth (nats, 10)

编辑: 虽然此处功能模式匹配非常理想,但您也可以使用 case ... of ... 。但是,辅助函数似乎是不必要的,因为您只需使用输入参数n作为迭代器:

fun nth (L, n) =
    case (L, n) of
         (NullList, _) => NONE
       | (Cons (x, xs), 0) => SOME x
       | (Cons (_, xs), n) => nth (xs (), n-1)

但是,您可能希望使该功能更加健壮:

fun nth (L, n) =
    let fun nth' (NullList, _) = NONE
          | nth' (Cons (x, xs), 0) = SOME x
          | nth' (Cons (_, xs), n) = nth' (xs (), n-1)
    in if n < 0 then NONE else nth' (L, n) end

这里有一个辅助函数可以确保只检查n < 0一次。

(您也可以raise Domain,因为负面指数没有明确定义。)