SML 模式匹配记录如何工作

Posted

技术标签:

【中文标题】SML 模式匹配记录如何工作【英文标题】:How does SML pattern matching records work 【发布时间】:2021-09-14 04:13:13 【问题描述】:

免责声明,这是在线课程的一部分,但我已经解决了作业。我的问题是关于记录工作的模式匹配?

所以在第一个函数中我不必指定记录的结构

fun generateName (ls , name)=
case ls of
[] => name::[]
  | x::xs =>

  first= x,
  middle= #middle name,
  last= #last name

:: generateName(xs, name);

在这个函数中我做。否则我会收到一个弹性记录错误。

fun createName (f, name :first:string, middle:string, last:string) =
case f of
x =>

  first= x,
  middle= #middle name,
  last= #last name

更令人困惑的是,这个没有错误

fun generateName2 (nms, name) =
let fun aux (ls, name, acc) =
    case ls of
        [] => name::acc
      | x::xs =>
        aux(xs, name, 
        
          first= x,
          middle= #middle name,
          last= #last name
         :: acc)
in
aux (nms, name, [])
end

什么时候必须指定记录字段?

【问题讨论】:

【参考方案1】:

SML 没有行多态性,所以编译器需要知道一条记录的所有字段名。

在返回列表的函数中,递归限制了可能的类型;如果name的类型为RgenerateName (ls , name)的类型为R list,则所有的字段名都可以从非空递归情况中推断出来。

中间的例子没有输入输出这样的关系,所以除非你指定输入字段名,否则SML不知道它们是什么。

【讨论】:

【参考方案2】:

@molbdnilos 的回答非常好。因为我坚信充分利用编程语言的优点可以使代码更容易推理,所以让我们稍微整理一下代码示例。理论上这属于评论,但不太适合这种级别的评论。

我希望这里显示的想法可以帮助您。好好学习!

fun generateName (ls , name)=
case ls of
[] => name::[]
  | x::xs =>

  first= x,
  middle= #middle name,
  last= #last name

:: generateName(xs, name);

当我们将case 视为函数体中的第一件事,并且它只是作用于其中一个参数时,我们可以在函数签名本身中使用模式匹配。

fun generateName([] , name) = name :: []
  | generateName(x::xs, name) = 
       first = x,
        middle = #middle name,
        last = #last name  :: generateName(xs, name);

我们还可以进一步使用模式匹配来消除提取函数体内记录字段的需要。

fun generateName([] , name) = name :: []
  | generateName(x::xs, name as first:string, middle:string, last:string) = 
       first = x,
        middle = middle,
        last = last  :: generateName(xs, name);

在您的第二个示例中,仅将一个参数与一个包罗万象的模式进行模式匹配是没有意义的。我们可以摆脱它。

fun createName (f, name :first:string, middle:string, last:string) =
   first = f,
    middle = #middle name,
    last = #last name 

如果我们将其作为模式提供,我们不必指定类型。

fun createName (f, first:string, middle:string, last:string) =
   first = f,
    middle = middle,
    last = last 

您的第三个代码示例也可以从这些想法中受益。

fun generateName2(nms, name) =
  let 
    fun aux([], name, acc) = name :: acc
      | aux(x::xs, name as  first:string, middle:string, last:string , acc) =
          aux(xs, name, 
               first = x,
                middle = middle,
                last = last  :: acc)
  in
    aux(nms, name, [])
  end

【讨论】:

以上是关于SML 模式匹配记录如何工作的主要内容,如果未能解决你的问题,请参考以下文章

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

SML中来自元组的“Curry”

我如何匹配一个字符串,直到某个模式在模式不出现时也可以工作?

Spark记录-Scala模式匹配

GWT:如何让正则表达式(模式和匹配器)在客户端工作

js正则匹配总结