2016-11-02 3 views
0

Я чрезвычайно новичок в sml. Я не могу понять, что не так для этой простой обратной функции, которую я пытаюсь написать.Ошибка типа в стандартной функции обратной связи ML

fun reverse [] = [] | 
    reverse (v1::rest) = (reverse(tl(rest)) @ v1) 

Это выход, когда я пытаюсь запустить обратное ([1, 2, 3]);

poly: : error: Type error in function application. 
Function: reverse : 'a list list -> 'a list 
Argument: ([1, 2, 3]) : int list 
Reason: 
    Can't unify int (*In Basis*) with 'a list (*In Basis*) 
    (Different type constructors) 
Found near reverse ([1, 2, 3]) 
Static Errors 

Я вижу, что это ошибка типа. Похоже, что обратное ищет 2 списка (я думаю .. «список списка кажется мне странным типом)? Есть ли проблема с настройкой шаблона/параметров? Спасибо за помощь.

+0

Теперь я вижу, что вместо @ у меня должно быть ::, но я все равно получаю аналогичную ошибку. – Nick

ответ

2

Вначале обратимся к неправильному вопросу.

'a list list означает список списков, как этот:

[[1,2], [3,4], [5,6]] : int list list 

который представляет собой список из списков целых чисел.

Общий вид вашей reverse функции

val reverse = fn : 'a list list -> 'a list 

Это происходит потому, что оператор @ имеет следующую сигнатуру (вы можете найти документы here).

val @ : 'a list * 'a list -> 'a list 

Таким образом, механизм вывода типа делает вывод, что v1 является 'a list, но это означает, что список входов содержит элементы типа 'a list и, следовательно, должны быть типа 'a list list.

Но что на самом деле имел в виду, чтобы добавить элемент v1 до конца обращенного хвоста, и это может быть легко достигнуто путем v1 в список одного элемента:

some_list @ [v1]

Далее вам не нужно tl(rest), так как rest уже является хвостом вашего списка входных данных. В качестве побочного примечания: более идиоматично писать tl rest, круглые скобки здесь несущественны.

Принимая во внимание вышесказанное, мы получаем следующую реализацию:

fun rev [] = [] 
    | rev (h::tl) = rev tl @ [h] 

Я должен предупредить вас, что эта функция является очень неэффективным, поскольку это временная сложность является квадратным (O (N^2)).

+0

Я заметил, что вышеприведенная функция дает результат, который по какой-то причине не включает последний элемент. Мой следующий вопрос заключается в том, как он также не работает, когда я просто меняю @ на :: и удаляю функцию tl()? – Nick

+0

Убивает мою ошибку, я все еще звонил в обратном направлении! Извините, и спасибо за помощь! Я также понимаю теперь, что :: нет никого рядом с правым, так как это просто образец (я очень лишен сна). Снова жаль об этом! – Nick

+0

Вы не можете добавить элемент в конце списка. '::' имеет тип ''a *' список -> 'список', поэтому тип inferencer снова выводит' 'список' для' v1' в этом случае (обратите внимание, что 'reverse' не будет вводить проверку вообще говоря, если вы меняете '@' и '::'). Списки несимметричны: вы можете легко добавлять элементы с помощью '::', но добавление намного сложнее.НТН –