Синтаксическая ошибка SML, оператор не является функцией. Я очень смущен

#functional-programming #sml #smlnj

Вопрос:

Я совершенно новичок в 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
 

Ответ №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 значение любого типа. Теперь давайте посмотрим на вложенное выражение , указанное repeat в определении times , и которое является

 ( x (plus( x y)) x)
 

Это заключенное в скобки выражение, скорее всего, получит обработку одного значения, проблема в том, что его тип не будет an int . И поэтому несоответствие типов.. о чем нам рассказывает компилятор.

Я могу попытаться исправить это, но не уверен, что эта попытка даст вам функционально правильный код. Однако все происходит примерно так…

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

И с компилятором все в порядке… потом.

Комментарии:

1. Спасибо. После дальнейших исследований я понял это. Но ваша помощь была потрясающей и очень ценной.