【问题标题】:SML Syntax error, operator is not a function. I am very confusedSML 语法错误,运算符不是函数。我很迷茫
【发布时间】:2021-11-01 18:23:41
【问题描述】:

我是 SML 的新手。有人可以解释为什么第四行给我这个错误吗?我完全不知道为什么。

fun plus x y = x + y;
fun twice f x = f ( f ( x));
fun repeat n f x = if n = 0 then x else repeat (n-1) f (f(x));
fun times x y = repeat( x (plus( x y)) x);
- val plus = fn : int -> int -> int
val twice = fn : ('a -> 'a) -> 'a -> 'a
val repeat = fn : int -> ('a -> 'a) -> 'a -> 'a
stdIn:4.25-4.41 Error: operator is not a function [tycon mismatch]
  operator: int
  in expression:
    (x (plus (x y))) x

【问题讨论】:

    标签: functional-programming sml smlnj


    【解决方案1】:

    为了扩展 @Nalin Ranjan 在他的回答中所说的内容,SML(或其他 ML 家族语言)语法的一个常见问题是理解函数应用程序语法。

    让我们考虑一个名为f的非常简单的函数:

    fun f x = x + 1
    

    此函数采用单个参数x 并将其转换为x + 1。这个函数的签名是int -> int。它需要一个 int 并返回一个 int。

    我们可以这样称呼它:

    f 4
    

    可以说 ML 家族语言中的函数只接受一个参数。如果我们希望f 获取两个整数并将它们相加,我们有两种方法可以完成此操作。首先,我们可以创建一个函数,它接受一个 int 并返回一个接受另一个 int 的函数,然后将它们相加。

    fun f x = fn y => x + y
    

    这个函数现在有签名int -> int -> int。添加一对括号,它可能更有意义:int -> (int -> int)。它是一个接受一个 int 并返回一个接受一个 int 并返回一个 int 的函数的函数。 SML 为我们提供了一种更方便的编写方式。

    fun f x y = x + y
    

    无论我们如何定义函数,我们都以相同的方式调用它:

    f 4 5
    

    此时括号仅用于消除操作顺序的歧义。我们可以这样调用f

    f(4)(5)
    

    但如果我们这样做,它就行不通了:

    f(4 5)
    

    因为4 5 看起来像函数应用程序,但4 不是函数,所以我们有语法错误。使用括号的有效方法是 f (f 1 2) 6

    这就引出了第二种方法来获得一个带有多个参数的 SML 函数。 我们没有

    我们不是创建一个返回函数的函数,而是简单地将一个元组传递给一个函数。

    fun f (x, y) = x + y
    

    在此示例中,(x, y) 是单个元组值,我们使用模式匹配为其两个组成值命名。规则与第一种方法完全相同,但它看起来更像许多更主流的语言。这种风格在 SML 社区中也很突出(Ocaml,相比之下通常使用第一种方法)。

    很难说这是一件好事,还是它的视觉相似性只会造成不必要的混乱。

    【讨论】:

      【解决方案2】:

      让我们依次看一下我们在这里定义的每个函数的定义:-

      val plus = fn: int -> int -> int
      val twice = fn: ('a -> 'a) -> 'a -> 'a
      val repeat = fn: int -> ('a -> 'a) -> 'a -> 'a
      

      而有错误的函数定义是

      fun times x y = repeat( x (plus( x y)) x);
      

      由于repeat 是在times 的定义中应用的函数,让我们看看作为参数提供给repeat 的表达式

      repeat (x (plus (x y)) x)
      

      现在根据repeat 的定义,它需要3 个参数...第一个是int 类型,第二个是函数('a -> 'a) 类型,第三个是'a 上的参数,这意味着任何值类型。现在让我们看看在times 的定义中提供给repeat 的子表达式,它是

      ( x (plus( x y)) x)
      

      这个带括号的表达式很可能会得到单个值的处理,问题是它的类型不是int。所以编译器告诉我们的类型不匹配。

      我可以尝试解决此问题,但不确定该尝试是否会为您提供功能正确的代码。然而,事情是这样的……

      fun times x y = repeat x (plus x) y;
      

      编译器一切正常……之后。

      【讨论】:

      • 谢谢。经过进一步研究,我想通了。但是您的帮助很棒,非常感谢。
      猜你喜欢
      • 1970-01-01
      • 2019-04-19
      • 2022-09-24
      • 1970-01-01
      • 1970-01-01
      • 2013-01-31
      • 2017-11-20
      • 1970-01-01
      • 2018-02-11
      相关资源
      最近更新 更多