我在sml中的代码出了什么问题?

时间:2015-03-17 04:34:22

标签: sml

我不知道为什么我的代码不起作用。

fun lookup _ [] = 0
  | lookup key ((k,v)::entries) =
    if k = key
    then v
    else (lookup key entries)

这是我在cmd中测试时发生的事情。

val lookup = fn : ''a -> (''a * int) list -> int
- lookup (1,[(1,2),(2,3)]);
val it = fn : ((int * (int * int) list) * int) list -> int

1 个答案:

答案 0 :(得分:4)

您的代码没有任何问题,您只是没有用足够的参数调用lookup。你在来自其他语言的初学者SML程序员中犯了一个常见的错误。我试着澄清一下。

首先,了解标准ML中最重要的功能是:

  

标准ML中的所有函数只接受一个参数。

此时您可能会感到困惑,因为您的lookup函数看起来好像有两个参数。它确实有,但不是真的。

有两个主要的解决方案" (我使用引号,因为这实际上是语言的一个很棒的特性),用于表示带有多个参数的函数:

1。使用curried函数

如果你需要编写一个在概念上需要三个参数的函数,那么你就写下这个:

fun quux a =
  fn b =>
    fn c =>
      (* do something with a, b and c *)

所以,quux是:

  • 一个函数,它接受一个参数a并返回
  • 一个函数,它接受一个参数b并返回
  • 一个函数,它接受一个参数c并返回
  • 使用abc
  • 计算的结果

您如何致电quux?像这样,对吧?

((quux a) b) c

但是函数应用程序已经是关联的,所以我们实际上可以这样写:

quux a b c

我们不需要括号来打电话"功能!在标准ML括号中,并不意味着将此功能称为“#34;”。当您想要更改关联性时,它们仅用于将表达式组合在一起,例如数学:(1 + 2) * 3

因为如上所述定义quux非常麻烦,所以语言中有一个句法快捷方式。而不是写这个:

fun quux a =
  fn b =>
    fn c =>
      (* do something with a, b and c *)

我们可以这样写:

fun quux a b c = (* do something with a, b and c *)

但是,他们是同一件事。 quux仍然是一个只接受参数a的函数,并返回一个带有参数b的新函数,该函数返回一个参数c的新函数。

好的,这是在Standard ML中表示多参数函数的一种方法。它也是您用来定义lookup的那个。

2。使用元组

表示多参数函数的另一种常用方法是接受一个元组(可能有2到任意数量的组件)。以上是使用元组的上述示例:

fun quux args =
  case args of
    (a,b,c) => (* do something with a, b and c *)

我们现在怎么称呼quux?像这样:

quux (a,b,c)

请注意,我在quux和元组之间放了一个空格。它是可选的,但是我一直这样做是为了记住标准ML中的函数应用程序是而不是用括号表示。 quux被调用,因为它被放在元组(a,b,c)之前。但是,元组确实需要括号,这就是你在上面看到它们的原因。

同样,和以前一样,定义quux这样很麻烦:

fun quux args =
  case args of
    (a,b,c) => (* do something with a, b and c *)

所以我们实际上可以使用语言的另一个很棒的特性,在参数位置进行模式匹配,这让我们写下这个:

fun quux (a,b,c) = (* do something with a, b and c *)

好的,现在我们可以回答你的问题了。


您使用curried函数语法定义lookup

fun lookup _ [] = 0

但你"叫" lookup使用元组语法,其中1是元组的第一个元素,[(1,2),(2,3)]是第二个元素。

lookup (1, [(1,2),(2,3)])

但是为什么编译器没有抱怨。在这个不幸的情况下,它并不是因为它发生了查找的第一个参数的类型是一个元组。所以,你基本上只用一个参数调用lookup

你想要的是:

lookup 1 [(1,2),(2,3)]

请注意,我不再定义元组。