#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. Спасибо. После дальнейших исследований я понял это. Но ваша помощь была потрясающей и очень ценной.