如何在 SML 中打印 if 语句
Posted
技术标签:
【中文标题】如何在 SML 中打印 if 语句【英文标题】:How to print in if statement in SML 【发布时间】:2021-06-23 08:21:28 【问题描述】:这是我试过的代码
fun printsl([], k) = true
| printsl(h::t) = if k > h then print(h) andalso printsl(t);
但是当我运行代码时,我得到以下错误
= stdIn:4.68-7.8 Error: syntax error: deleting SEMICOLON ID
stdIn:8.1 Error: syntax error found at EOF
该函数的目标是打印列表中小于值k
的任何数字
【问题讨论】:
必须有一个else
分支——条件是一个表达式,而不是一个语句,所以在所有情况下都必须产生一个值。此外,所有定义子句必须采用相同数量和类型的参数 - 您有一个采用 ('a list * 'b)
和一个采用 int list
(并且 k
未绑定在该子句中)。也许您应该看一下 SML 的介绍?
另外,print
的类型是string -> unit
。不能打印整数,结果不能是andalso
的操作数。
附带说明,如果这是 SML 介绍中的一个练习并且它说“输出”,那可能是返回一个值,而不是打印任何东西。
如果您确实需要打印,您可能会发现函数Int.toString : int -> string
很有帮助。
【参考方案1】:
这里有一些问题。让我们从您的函数签名开始。
在第一行,您的函数有 2 个参数、一个空列表以及 k
的任何类型(这还不重要)。然后在第二行,函数只接受一个参数,一个非空列表。
这两行应该匹配,看起来像:
fun printsl([], k) = ...
| printsl(h::t, k) = ...
现在让我们考虑一下andalso
的用法。 andalso
是一个运算符,它接受两个布尔值并返回一个布尔值。可以认为有签名bool * bool -> bool
。
您的使用 print(h) andalso printsl(t)
与此签名不匹配。
print
的类型是string -> unit
,所以print(h)
的类型是unit
(假设h
是一个字符串)。因此,andalso
的用法不正确,因为每一侧的类型都不是布尔值。
我们可以简单地执行两个语句(print(h); printsl(t, k))
,而不是使用andalso
。像这样的序列是返回最后一个值的表达式。也就是说(x; y; z)
返回z
。
fun printsl([], k) = true
| printsl(h::t, k) = if h < k then (print(h); printsl(t, k));
但是,由于 SML 中的 if-else 构造是一个表达式,并且 必须 有一个匹配的 else,所以这仍然被打破,因此您可以使用以下任一种:
fun printsl([], k) = true
| printsl(h::t, k) =
if h < k then (print(h); printsl(t))
else printsl(t, k);
fun printsl([], k) = true
| printsl(h::t, k) = (
if h < k then print(h) else ();
printsl(t, k)
);
我个人更喜欢后者,因为它可以防止重复 printsl
。
这段代码可以编译,但是签名错误。由于我们直接使用h
作为print
的参数,所以推断其类型为string
。这意味着编译器确定printsl
的类型为string list * string -> bool
,而我们的目标是int list * int -> bool
。
这可以通过将调用 print(h)
更改为 print(Int.toString h)
来纠正,给我们:
fun printsl([], k) = true
| printsl(h::t, k) = (
if h < k then print(Int.toString h) else ();
printsl(t, k)
);
现在这是一个函数,它将打印给定列表中小于k
的所有值,但它总是返回true。这没有提供额外的信息,所以我倾向于将签名更改为int list * int -> unit
,给我们(最后):
fun printsl([], k) = ()
| printsl(h::t, k) = (
if h < k then print(Int.toString h) else ();
printsl(t, k)
);
也可以使用List.app
和List.filter
以更实用的方式编写整个程序。
fun printsl (xs, k) =
List.app
(fn y => print (Int.toString y))
(List.filter
(fn x => x < k)
xs);
【讨论】:
以上是关于如何在 SML 中打印 if 语句的主要内容,如果未能解决你的问题,请参考以下文章