如何在 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 -&gt; bool,而我们的目标是int list * int -&gt; 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 -&gt; unit,给我们(最后):

fun printsl([],   k) = ()
  | printsl(h::t, k) = (
    if h < k then print(Int.toString h) else ();
    printsl(t, k)
  );

也可以使用List.appList.filter 以更实用的方式编写整个程序。

fun printsl (xs, k) =
  List.app
    (fn y => print (Int.toString y))
    (List.filter
      (fn x => x < k)
      xs);

【讨论】:

以上是关于如何在 SML 中打印 if 语句的主要内容,如果未能解决你的问题,请参考以下文章

如何比较和搜索列表中的元素与列表 SML 中的元组

SML 模式匹配记录如何工作

请教问Mybatis 如何打印SQL语句

请教问Mybatis 如何打印SQL语句

在 SML 中查找 2-3 树中的节点数

If & Else & SML 中的模式匹配?