在SML中查看记录类型?

时间:2016-11-08 16:12:27

标签: list tuples sml

我有这种特殊类型。

type taken = {course:string, student:int, grade:real};

我想查看此类型的列表,找到匹配的课程和学生。如果我找到一个,那么我必须将等级更改为预设变量G.以下就是我现在所拥有的。

exception unTaken;
fun updateGrade (T:taken, []:taken list) = raise unTaken
  | updateGrade (T, {course = #course(T), student = #student(T), ...}::rest) =
    {course = #course(T), student = #student(T), grade = G}
  | updateGrade (T, TL) = updateGrade (T, (tl TL));

如果到达了列表的结尾,我会引发异常。 第二个选项是,如果它与T中的课程和名称匹配,则将其设置为相同的课程和学生,但将G更改为预设变量。否则,请继续浏览列表。

问题是,我一直遇到类似于以下错误的错误

stdIn:3.21-3.28 Error: syntax error: deleting  HASH ID
stdIn:3.43-3.52 Error: syntax error: deleting  HASH ID LPAREN
stdIn:3.53 Error: syntax error found at RPAREN

知道发生了什么事吗?我还可以问一下如何调试这些错误吗?

1 个答案:

答案 0 :(得分:2)

以下是一些出错的方法:

  • 作为惯例,将变量名称保持为小写,将值构造函数保持为大写。
  • 不要在相同的模式中使用相同的变量两次(您在几个地方使用T)。一些模式匹配语言(Erlang,Prolog)允许这意味着这些变量所涵盖的值应该是等价的,但标准ML不支持这一点。
  • 不要在模式中使用记录getter #course / #student。它们的行为类似于函数的宏。您可以对记录的某些部分进行模式匹配,但语法略有不同(请参阅下面的第二个示例)。

这是一个固定版本:

fun updateGrade (t1 : taken, []) = raise unTaken
  | updateGrade (t1 : taken, t2::ts) =
    if #course t1 = #course t2 andalso #student t1 = #student t2
    then t1 :: ts
    else t2 :: updateGrade (t1, ts)

这是一个在记录上执行模式匹配的固定版本:

fun updateGrade (t1 : taken, []) = raise unTaken
  | updateGrade (t1 as { course = course1, student = student1, ... },
                 (t2 as { course = course2, student = student2, ... })::ts) =
    if course1 = course2 andalso student1 = student2
    then t1 :: ts
    else t2 :: updateGrade (t1, ts)
  

我还可以问一下如何调试这些错误吗?

由于编译器在语法错误发生时通常仍然没有帮助,我不确定是否有更好的解决方案,而不是将代码显示给其他人,或者将其与您知道的最相似的教科书示例进行比较。标准ML缺少示例代码,并且记录语法比大多数语言的其余部分更加繁琐。