ML代码错误的原因

时间:2012-09-27 00:16:27

标签: sml ml

以下代码只是一种原型。我想知道的是为什么它无法编译。

fun test(list) = 
    let 
    fun inner(list) = 
    let
        val from = #1(hd(list))
        in
        if null(tl(list)) = false then innerinner(tl(list),from)
        else false
        end 
    fun innerinner(list,from) = 
        if #2(hd(list)) = from then true
        else if null(list) = false then innerinner(tl(list),from)
        else false
    in
    inner(list)
    end;

错误消息是:

test.txt:7.34-7.44 Error: unbound variable or constructor: innerinner
test.txt:3.2-9.6 Error: unresolved flex record
(can't tell what fields there are besides #1)
test.txt:10.2-13.13 Error: unresolved flex record
(can't tell what fields there are besides #2)

uncaught exception Error
raised at: ../compiler/Toplevel/interact/evalloop.sml:66.19-66.27
....

我是ML编程的初学者。谁能教我什么是错的?

1 个答案:

答案 0 :(得分:2)

你在这里发生了很多事情。如果我们首先看看你得到的错误。

  1. 未绑定的变量或构造函数:innerinner

    在sml中,你不能在声明之前“使用”它们。它很容易在你的情况下修复 交换函数声明,从而在innerinner之前声明inner

    如果您最终遇到想要声明两个相互递归的情况 功能,那么这不是一个选项。在这种情况下,您必须使用关键字and

  2. 未解决的弹性记录

    这有点复杂。这是一个类型错误,与事实有关 元组在内部表示为记录(我建议你去阅读 它)。因此,当您没有提供足够的信息时,类型系统会抱怨。

    我认为this QA解释得非常好。总之,你不能拥有无界的元组 因此你需要向类型系统明确它包含多少元素。这个 可以通过显式键入注释函数声明来完成。 但一般情况下,您应该尽可能经常使用模式匹配。

  3. 通常,您应始终使用模式匹配而不是元组选择器(#1,#2,...)或列表选择器(hd或tl)。你刚刚看到为什么元组选择器可能“坏”但是使用列表选择器而不测试列表是否为空首先会给你运行时错误(例外)。

    在你的代码中加入这样的测试用例会“搞砸”,并使阅读变得混乱。但是如果你使用模式匹配,你的函数定义中会有一些很好的明确切割情况。 通常,你会倾向于编写较少的代码(在我看来)。

    顺便说一下,你不需要在函数的单个参数周围添加括号,例如test函数的主要定义。

    总而言之,你的所有功能都可能是这样的:

    fun test list =
    let
      fun innerinner ((x1, x2)::xs,from) =
          if x1 = from then true
          else innerinner(xs,from)
        | innerinner ([], from) = false
    
      fun inner ((x1, x2)::xs) = innerinner(xs,x1)
        | inner [] = false
    in
      inner(list)
    end