Sml 如何在ML中创建平面列表函数?
我得到一个练习,要求我编写一个函数Sml 如何在ML中创建平面列表函数?,sml,ml,Sml,Ml,我得到一个练习,要求我编写一个函数flatlist,该函数获取列表列表,并通过返回原始列表中所有列表的串联来“展平”列表 例如: flatlist([1,2], [6,7], [9]) = [1,2,6,7,9] 下面的代码就是我尝试的代码 fun flatlist([]) = [] | flatlist(a::rest) = (a::rest); 我在编写函数时没有收到错误消息,但在REPL中尝试函数并在示例中应用该函数时遇到问题。要求您编写的函数通常称为concat,并且恰好位于标准
flatlist
,该函数获取列表列表,并通过返回原始列表中所有列表的串联来“展平”列表
例如:
flatlist([1,2], [6,7], [9]) = [1,2,6,7,9]
下面的代码就是我尝试的代码
fun flatlist([]) = []
| flatlist(a::rest) = (a::rest);
我在编写函数时没有收到错误消息,但在REPL中尝试函数并在示例中应用该函数时遇到问题。要求您编写的函数通常称为
concat
,并且恰好位于标准库中的List.concat
名称下。尽管如此,编写这样一个递归函数仍然是一个很好的练习。你的函数确实会进行类型检查和编译,除了有一个你还没有发现的细微缺陷
关于语法
首先,关于空格和括号,我可能会对您的第一次尝试的格式稍有不同:
(* Before *)
fun flatlist([]) = []
| flatlist(a::rest) = (a::rest);
(* After *)
fun flatlist [] = []
| flatlist (xs :: xss) = xs :: xss
这里的要点是:
- 因为第一个元素本身就是一个列表,所以我喜欢给它取一个复数名,
,因为其余的是一个事物列表,所以我喜欢给它取一个双复数名。但是xs
xs::rest也可以。这样我们就不会把读者和
混淆,这是一个单数任意值的好名字x
模式周围的括号是不必要的,因为[]
是单个组合符,因此不需要消除歧义。但是,模式xs::xss确实需要一个括号,因为它包含一个中缀模式构造函数,该构造函数接受多个参数。如果我们忽略它,就像这样:[]
我们将收到以下警告(在莫斯科):fun flatlist [] = [] | flatlist xs :: xss = xs :: xss
- 另一方面,
函数体周围的括号不需要括号,因为函数体在语法上是为单个表达式保留的,xs::xss
。这里没有必要消除歧义xs::xss
- 结尾
也不是严格必需的,除非您将此函数复制粘贴到REPL中,而不是将其放入文件中。所以,只要你的函数很短,你就只需将它们复制粘贴到REPL中来尝试它们,拥有代码>很好。当您开始构建更大的函数并一次执行整个文件时,您最好将其忽略
f(x)
“前面是函数名,中间是它的参数
SML函数不同:函数应用程序的最简单形式类似于fx
。需要使用括号来消除歧义,例如,f(x+2)
与(f x)+2
,但不需要括号来表示这是函数应用程序。函数名和值之间的空格会处理这个问题
分析初始解
您遇到的第一个问题是将列表列表传递给函数。在您的示例中,您实际要做的是传递一个三元组,(x,y,z)
,其中x
,y
和z
是列表。此值的类型为int list*int list*int list
,而不是函数flatlist
所期望的int list
。这是因为SML中的括号(当括号中有逗号时)用于表示元组,而不是“函数的参数”
尝试一个整数列表,它会给出:
- flatlist [[1,2], [6,7], [9]];
> val it = [[1, 2], [6, 7], [9]] : int list list
塔达!等等
让我们通过一次减少表达式的一部分来评估您第一次尝试的flatlist
。在这里,我使用⇒代码>意思是“减少到”:
因此,您当前的flatlist
是一个非常复杂的列表
正确解决方案的提示
因此,您拥有基本的递归权限,但在每个递归状态下需要执行的操作有点不正确。它不仅仅是作为函数体的xs::xss
,因为这将产生与输入完全相同的输出。对于xss
中的所有列表,您必须以某种方式将列表xs
的元素与下一个列表的元素递归地连接起来
提示:@
运算符(发音为“append”)
- flatlist [[1,2], [6,7], [9]];
> val it = [[1, 2], [6, 7], [9]] : int list list
flatlist [[1,2], [6,7], [9]] (* x = [1,2], xs = [[6,7], [9]] *)
⇒ [1,2] :: flatlist [[6,7], [9]] (* x = [6,7], xs = [[9]] *)
⇒ [1,2] :: [6,7] :: flatlist [[9]] (* x = [9], xs = [] *)
⇒ [1,2] :: [6,7] :: [9] :: flatlist [] (* base case *)
⇒ [1,2] :: [6,7] :: [9] :: [] (* just another way to write *)
⇒ [[1,2], [6,7], [9]]