Вопросы по проверке и логическому выводу типа SML

Прежде всего, поскольку вопрос каким-то образом связан со школьным проектом, я не думаю, что размещение моего кода уместно. К тому же, как я объясню позже, у меня есть только модифицированная версия рассматриваемого кода.

И я объясняюсь. Я должен реализовать версию алгоритма Дейкстры с использованием очереди приоритетов. Я думал, что простой функциональный способ сделать это - определить функцию dijkstra с входами очереди и целевого узла и вспомогательной функцией для постановки в очередь узлов, которые являются соседями для элемента списка, который только что был исключен из очереди. К сожалению, вспомогательная функция не проверила тип - Unresolved Flex Record.

Пока может показаться, что код важен, но позвольте мне добавить еще одну деталь. Поскольку граф был 4-каноническим (что означает, что каждый узел имеет ровно четыре соседа), я представил его как матрицу, используя арифметику модулей. Чтобы упростить свой алгоритм, я использовал этот факт, чтобы переписать его и использовать 4 дополнительные вспомогательные функции - по одной для каждого возможного хода - вместо четырех if внутри первой вспомогательной функции. Каждая из четырехходовых функций возвращает истину, если мы должны посетить этот узел (что означает, что стоимость, которая нам понадобится таким образом, меньше, чем текущая необходимая стоимость), и ложь, если нет. А первый помощник просто возвращает кортеж из четырех логических переменных. Наконец, я скопировал код постановки в очередь, который не работал при моей первой попытке, в тело кода Дейкстры, и внезапно он выполнил проверку типов.

Я понимаю, что это все еще может быть неясным, и, возможно, вы можете только догадываться о том, что происходило. Но я действительно очень озадачен. Я искал этот сайт и базу SML и обнаружил, что такого рода ошибка возникает в следующем случае:

f (x,y,z) = ...

где z не используется, поэтому средство проверки не может определить, что это такое. Я уверен, что в моей проблеме это не так, поскольку я просто копирую и вставляю код (не очень хороший метод, который я знаю, но хорошо). Отсюда я пришел к выводу, что проблема в том, что проверка типов не работает с вызовами функций. Я поискал снова и нашел объяснение алгоритма Хиндли Миллера. И из того, что я понял каждый раз, когда он встречается, функция будет считать, что это a-> b в качестве первого шага, а затем перейду к определению функции и завершит задачу. Итак, я вернулся к исходной точке и решил задать этот вопрос здесь, чтобы лучше понять вывод типов или намек на то, что происходит.

P.S. 1) Несмотря на то, что я изо всех сил пытался объяснить вопрос, он все еще неясен или слишком широк, дайте мне знать, и я удалю, без проблем. P.S. 2) Меньший и более простой вопрос: я прочитал, что №1 не рекомендуется брать 1-й элемент кортежа, и иногда он даже не проверяет тип, и вместо этого следует использовать сопоставление с образцом. Не могли бы вы это объяснить? P.S. 3) Кто-то может спросить, почему я задал этот вопрос, раз уж я решил проблему со второй попытки. Лично я не считаю решенным, а скрытым.

Заранее спасибо и извините за размер вопроса.

Ссылки:

Ошибки SML / NJ

P.S. 2)

Хиндли-Миллер

ОБНОВЛЕНО: после дополнительных поисков я догадываюсь, что было не так. Я реализовал приоритетную очередь, не настроенную для моей проблемы, а более общую. Итак, вывод типа очереди с приоритетом имел место, когда я впервые поставил элемент в очередь. Но после постановки в очередь моего исходного узла и вызова dijkstra очередь снова станет пустой (мой dijsktra удалял из очереди первый элемент, проверяя, является ли он целевым узлом), и первый вызов вспомогательной функции, которая добавляет узлы, будет иметь пустую очередь как один своих аргументов. Возможно, пустая очередь не имеет типа, и это вызвало ошибку?


person cgss    schedule 12.06.2017    source источник
comment
Какой у Вас вопрос?   -  person Simon Shine    schedule 12.06.2017
comment
@Simon Shine Мой вопрос в том, почему enqueue не вводил команду resolve, когда выполнялся во второй функции, но имел тип, когда он был перемещен внутри Dijkstra; По-разному ли логический вывод работает с функциями? Или я правильно понял и может быть что то другое?   -  person cgss    schedule 12.06.2017
comment
@cgss, это очень поможет нам увидеть какой-то рабочий / неработающий код, даже если вопрос более общий, чем этот.   -  person Ionuț G. Stan    schedule 12.06.2017
comment
Кроме того, вы видели этот вопрос? stackoverflow.com/questions/13497125/   -  person Ionuț G. Stan    schedule 12.06.2017
comment
@ Ionut G. Stan Я снова прошу прощения за то, что не существует, но я думаю, что объясню mysef. Может, стоит попробовать написать псевдокод или что-то в этом роде? Как вы думаете, это может помочь? Также я увидел вопрос: это ссылка на P.S.2). Я помог мне выполнить вторую попытку, но, как вы, возможно, заметили, не объяснил почему, и это привело меня к P.S.2)   -  person cgss    schedule 12.06.2017
comment
Всегда рекомендуется включать код, желательно достаточно, чтобы сделать его минимально воспроизводимым примером. Откровенно говоря, поскольку вопрос каким-то образом связан со школьным проектом, я не думаю, что публикация моего кода уместна, имеет мало смысла. Трудно ответить на вопросы, касающиеся кода, который вы не видите. Вы почти всегда можете предоставить образец кода, который иллюстрирует проблему, даже если исходный код слишком велик для публикации или не может быть опубликован по какой-либо другой причине.   -  person John Coleman    schedule 12.06.2017
comment
@John Coleman Под образцом кода вы подразумеваете часть исходного кода или что-то вроде псевдокода?   -  person cgss    schedule 12.06.2017
comment
Актуальный код. В идеале кто-то должен иметь возможность взять ваш код и воспроизвести любую проблему, о которой вы спрашиваете. Внимательно прочтите минимальный воспроизводимый пример. Единственные альтернативы - это не псевдокод или ваш исходный код. При необходимости вы можете написать код (на основе исходного кода) для самого вопроса.   -  person John Coleman    schedule 12.06.2017


Ответы (1)


Я догадываюсь, о чем вы спрашиваете.

У меня есть функция enqueue, которая не работает в одном контексте, но работает в другом. Почему? Он использует макрос #1, и я читал, что #1 не рекомендуется брать 1-й элемент кортежа, и иногда он даже не проверяет тип, и вместо этого следует использовать сопоставление с образцом.

В стандартном ML #1 - это макрос. Он ведет себя как функция, но, в отличие от функций, он перегружается для любого кортежа / записи с полем 1 в нем. Если вы не укажете, какой тип кортежа вы передаете функции, использование #1 не устранит неоднозначность. Например,

- fun f pair = #1 pair;
! Toplevel input:
! fun f pair = #1 pair;
!              ^^
! Unresolved record pattern

Но присвоение ему типа (либо посредством явной аннотации типа, либо в контексте, где тип может быть выведен другими способами) работает хорошо.

- fun f (pair : int * int) = #1 pair;
> val f = fn : int * int -> int

Я не знаю, обозначил бы я #1 как однозначно запрещенный и сопоставление с образцом как единственный вариант, [edit: ..., но у этого ответа на переполнение стека, на который ссылается Ионуț Г. Стэн, есть некоторые аргументы. ]

У обоих есть свои преимущества и недостатки. В качестве альтернативы вы можете создать однозначные геттеры, которые работают только с типом кортежа, с которым вы работаете. Например,

fun fst (x, _) = x
fun snd (_, y) = y
person Simon Shine    schedule 12.06.2017
comment
Это на самом деле отвечает на мой маленький вопрос (P.S.2), так что спасибо! (Я проголосовал за, но это не в счет). Хотя я попрошу прояснить то, что вы высказали. Предположим, у нас есть удовольствие f, как вы определили его в начале (без объявления типа). Если средство проверки говорит, что хорошо, я буду знать, что это такое, как только вы позвоните, тогда нет ограничений, если вы хотите сначала вызвать его с помощью двухэлементного кортежа. и позже с 3-элементным или даже если вы вызываете его с целочисленным кортежем, а затем с помощью строкового кортежа. Теперь, поскольку ML не хочет позволять программисту делать такие ошибки, он с самого начала будет говорить об ошибке шаблона? - person cgss; 12.06.2017
comment
(У меня заканчиваются символы). Вы хотите, чтобы вы имели в виду не устранять неоднозначность, потому что он перегружен? Я также должен упомянуть, что этого не произошло с enqueue, а также каждый аргумент использовался либо внутри функции, которая добавляла узлы, либо в базовой функции dijkstra. - person cgss; 12.06.2017
comment
@cgss: Извините, вам придется быть более лаконичным. Понятия не имею, о чем вы спрашиваете. Комментарии к Stack Overflow не идеальны для последующей беседы. В идеале вы должны задать краткий вопрос и получить краткий ответ, а при необходимости обновить свой вопрос, если есть что-то конкретное. Похоже, вы хотите понять, как вывод типов работает на фундаментальном уровне. Вы можете прочитать статьи, ссылки на которые приведены в этом ответе. И вы можете понять, что означает перегрузка функции / оператора. - person Simon Shine; 12.06.2017
comment
Еще раз прошу прощения, но позвольте мне еще один комментарий. Я прочитал предоставленные вами ссылки, и хотя я думаю, что у меня есть фундаментальное понимание вывода типов, они помогли мне сделать еще один шаг. Поэтому я обновлю свой вопрос, чтобы добавить новую информацию. (Раньше я видел перегрузку в C ++ и Java, но никогда в функциональном языке, кроме обычных случаев). - person cgss; 12.06.2017