如何使用sml编写将2元组列表转换为扁平列表的函数?

问题描述 投票:0回答:2

例如,我遇到了一个问题,需要将元组列表转换为扁平列表:

[((1,2),(3,4),(5,6)]可以变成[1,2,3,4,5,6]

我试图编写这样的函数:

fun helper2(nil,b) = []
|   helper2(a,nil) = []
|   helper2(a::l1,b::l2) =l1::l2

fun flatten2 [] = []
|   flatten2 ((a,b)::tl) = helper2(a,b)

显示:

val flatten2 = fn : ('a list * 'a list list) list -> 'a list list

并且当我尝试使用命令flatten2[(1,2),(3,4),(5,6)];运行它时它会给我以下错误信息:

stdIn:1.2-1.29 Error: operator and operand do not agree [overload conflict]
  operator domain: ('Z list * 'Z list list) list
  operand:         ([int ty] * [int ty]) list
  in expression:
    flatten2 ((1,2) :: (3,4) :: (<exp>,<exp>) :: nil)

我的问题是:

  1. 为什么SML将a和b值视为列表,而不仅仅是a和b
  2. 如何修改我的代码,以便SML可以将a和b视为'a和'b未列出
  3. 如何使此代码按应有的方式工作?

感谢

list function sml
2个回答
2
投票

第一个问题:关于为什么类型以('a list * 'a list list)出现是因为类型推断正在看这部分代码:

|   helper2(a::l1,b::l2) =l1::l2
                            ^^
                           here

请记住,“ cons”(::)运算符的类型为'a -> 'a list -> 'a list,它将单个元素粘贴到相同类型元素的列表上。因此SML得出结论,无论l1l2是什么,其关系是l2l1的列表。

fun helper2(nil,b) = []

表示a必须是列表,因为nil的类型为'a list。因此,l2必须是列表列表(某些类型为'a)。

问题2和3:我不太确定如何在编写代码时对其进行更正。我可能会写这样的东西:

fun helper2 [] accum = List.rev accum
|   helper2 ((a,b)::tl) accum =  helper2 tl (b :: a :: accum);

fun flatten2 list = helper2 list [];

helper2完成所有肮脏的工作。如果输入列表为空,那么我们就完成了,我们可以返回我们一直在建立的反向accumulator。第二种情况是我们实际上将东西添加到累加器中。我们在列表的头和尾进行模式匹配。此模式匹配表示输入的类型为('a * 'a) list(两个元素均为相同类型的元组列表)。在头部,我们有一个元组,分别命名第一个和第二个元素ab。我们先将a加上b放在累加器上,然后递归调用列表末尾的helper2。最终,我们将仔细检查列表中的所有元素,然后仅剩下累加器,回想起来,它具有所有元素,但顺序相反。调用List.rev会反转累加器,这就是我们的答案。

并且当我加载并运行它时,我得到这个:

- flatten2 [(1,2), (3,4), (5,6)];
val it = [1,2,3,4,5,6] : int list

0
投票

为什么SML将a和b值视为列表,而不仅仅是a和b

克里斯已经深入回答了。

您正在将a作为第一个参数传递给helper2,后者需要一个列表作为其第一个参数。然后,您将b作为第二个参数传递给helper2,该参数使用第二个参数b::l2(也是一个列表)作为列表的结尾,其中a是头。因此b必须是这些列表的列表。

这没有任何意义,很可能是语法混乱的结果:您在a中传递了您对单个元素bflatten2的看法,但是当您在[ C0]现在是lists,其头分别称为helper2a。那些不是相同的ba

如何修改我的代码,以便SML可以将a和b视为'a和'b未列出

您可以放弃辅助函数的开头:

b

具有帮助器功能的目的是使它可以在递归期间累积结果,因为此版本的fun flatten2 [] = [] | flatten2 ((a,b)::pairs) = a :: b :: flatten2 pairs 使用大量的堆栈空间。它可以使用一个额外的参数来做到这一点,因此flatten2无需提及:

这是克里斯制作的版本。

如何使此代码按应有的方式工作?

您可以通过多种方式编写此代码。提到了两种使用显式递归的方法。

这里是使用高阶函数的一些替代方法:

flatten2
© www.soinside.com 2019 - 2024. All rights reserved.