标准ML扩展列表

时间:2018-10-10 01:03:58

标签: sml

  

方向

     

函数=INDEX(Sheet1!A:A, MATCH("*"&A2, Sheet1!B:B, 0)) 接收任何类型的列表和整数   数字expand,并返回一个列表,其中输入列表的每一项   复制了n次。例如,展开[1,2,3] 3必须为   评估为[1,1,1,2,2,2,3,3,3]。函数的类型必须为“ a   list→int→‘列表。

这是我的解决方案,其中我通过具有两个功能对要求稍加作弊。当我移至列表中的下一个项目时,我正在努力将n重置为原始值。在实现过程中,我将原始n值保存到了n,但从未更改过。我该如何消除对s的需求?

s

3 个答案:

答案 0 :(得分:3)

定义助手功能不是“欺骗”,这很好。
定义错误类型的函数是一个更大的问题-expand的类型对练习而言比最终获得的函数数更为重要(请注意,说明中指出“必须是”什么类型) ,但不允许您定义辅助函数)。

您遇到了问题,因为您试图一次“攻击”整个输入列表。
当您遇到“用列表的每个元素执行X运算”的问题时,要做的第一件事就是考虑“编写一个用 one 运算X的函数,然后List.map进行运算”

如果我们有一个函数可以重复k次,我们可以将其应用于每个列表元素。

我们可以写repeat: int * 'a -> 'a list,但这既需要数字又需要东西,并且在任何地方map都不方便。
如果我们可以动态地“固定”数字并获得函数'a -> 'a list,那就太好了。
如果您以方便的顺序提供参数,则Currying可以使您做到这一点。

fun repeat 0 i = []
  | repeat n i = i :: repeat (n - 1) i;

加载并测试:

val repeat = fn : int -> 'a -> 'a list
val it = () : unit
- repeat 3 4;
val it = [4,4,4] : int list

到目前为止看起来不错。
现在,我们可以编写repeat 4并获得一个接受“某物”并重复四次的函数。

让我们使用它:

- fun expand xs n = List.map (repeat n) xs;
val expand = fn : 'a list -> int -> 'a list list

该类型看起来不太好。让我们看看我们刚刚创建的内容。

- expand [1,2,3] 3;
val it = [[1,1,1],[2,2,2],[3,3,3]] : int list list

几乎正确-列表应为“扁平”。

幸运的是,List structure具有帮助以下功能的功能:concat: 'a list list -> 'a list,它获取列表列表并将其附加在一起,因此我们可以将结果传递给该列表:

- fun expand xs n = List.concat (List.map (repeat n) xs);
val expand = fn : 'a list -> int -> 'a list

那看起来更好。

- expand [1,2,3] 3;
val it = [1,1,1,2,2,2,3,3,3] : int list

答案 1 :(得分:1)

  

这是我的解决方案,其中我通过具有两个功能来对要求稍加作弊。

这不是问题。编写标准ml时,使用helper函数是好的。特别地,这里的辅助函数是尾递归,它将优化堆栈框架。有时(不是这里)模式的嵌套大小写是一种替代方法,但是由于没有尾递归,所以代价是需要更多的内存。

  

我该如何消除对s的需求?

我不知道您为什么不喜欢多余的s。但是我有一个解决方案:使用闭包将其隐式保存。

紧凑的风格:

fun expand [] n =  []
    | expand (node::list) n =
      let   fun n_times f n x = if n = 0 then x else f (n_times f (n-1) x) 
      in    n_times (fn list => case list of node::list => node::[node]) n [node] @ expand list n end

更具可读性的样式:

fun expand [] n =  []
  | expand (node::list) n =
    let
        fun n_times f n x =
            if n = 0
            then x
            else f (n_times f (n-1) x)
    in
        n_times (fn list => case list of node::list => node::[node]) n [node]
        @
        expand list n
    end

此闭包(fn list => case list of node::list => node::[node])不包括额外的s,但要做的是帮助n_times完成n次弊端。我想这就是你想要的

顺便说一句,要求expand [1,2,3] 3‘a list→int→‘a list要求您使用咖喱函数代替元组/非咖喱函数(标准ml中的所有参数都只是一个元组)。因此,我上面给出的解决方案使用了curry function(expand [] nn_times f n x)。您还可以使用一个帮助函数将非咖喱函数转换为咖喱函数:

fun curry_helper f x y z = f (x, y, z) 

如果您不了解某个地方,请随时发表评论。

答案 2 :(得分:1)

以下是使用标准库功能的解决方案:

AmazonS3Config

这是另一个:

fun expand (xs, n) =
    List.concat (List.map (fn x => List.tabulate (n, fn _ => x)) xs)