Декларация подписи изменена при компиляции

Когда я пытаюсь скомпилировать свой код, я получаю следующую ошибку

Error: Signature mismatch:
       ...
       Values do not match:
         val filter_map : ('b -> 'b option) -> 'b t -> 'b list
       is not included in
         val filter_map : ('b -> 'a option) -> 'b t -> 'a list
       File "set.ml", line 7, characters 2-55: Expected declaration
       File "treeSet.ml", line 105, characters 10-20: Actual declaration

Однако моя подпись на самом деле объявлена ​​​​следующим образом.

module type SetS = sig
  type 'a t

  val empty : 'a t
  val insert : 'a t -> 'a -> 'a t
  val contains : 'a t -> 'a -> bool
  val filter_map : ('a -> 'b option) -> 'a t -> 'b list
end

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

Какова реализация функции? OCaml предполагает, что 'a и 'b должны быть одинаковыми в зависимости от реализации, поэтому сигнатура, в которой они могут различаться независимо, не допускается. Пожалуйста, отредактируйте вопрос, чтобы показать реализацию, и я буду рад написать ответ, объясняющий, откуда он получает эту информацию.

Silvio Mayolo 22.04.2022 22:38

Не видя кода, я бы просто прокомментировал, что вы не можете сделать код более полиморфным, чем он есть на самом деле, объявив его таковым. Скорее всего компилятор прав насчет типа :-)

Jeffrey Scofield 22.04.2022 22:38
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
2
42
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

module type Expected = sig
  val filter : ('a -> bool) -> 'a list -> 'a list
end

и мы пишем,

module Real : Expected = struct
  let filter = List.filter_map
end

Сообщение об ошибке, которое мы получим, будет,

Signature mismatch:
Modules do not match:
  sig val filter : 'a list -> f:('a -> 'b option) -> 'b list end
is not included in
  Expected
Values do not match:
  val filter : 'a list -> f:('a -> 'b option) -> 'b list
is not included in
  val filter : ('a -> bool) -> 'a list -> 'a list

Итак, проблема в том, что предложенная нами реализация filter имеет тип 'a list -> f:('a -> 'b option) -> 'b list, но то, что мы действительно хотели и ожидали от типа filter, это ('a -> bool) -> 'a list -> 'a list. Об этом говорит сообщение об ошибке.

Применительно к вашему случаю ваша реализация имеет предполагаемый тип ('b -> 'b option) -> 'b t -> 'b list, который не соответствует требуемому типу ('b -> 'a option) -> 'b t -> 'a list. Обратите внимание, что ваш тип менее общий. Он фильтрует список, не меняя тип элемента. Таким образом, он может фильтровать только карту int list в int list, string list в string list и так далее, в отличие от более общей реализации, которая может отображать int list в string list.

Чтобы устранить проблему, вам необходимо тщательно проверить свою реализацию. Убедитесь, что у вас нет инструкций ветвления (например, if/then/else, match), чтобы одна ветвь возвращала элемент или элементы входного списка, а другая ветвь возвращала элемент или элементы выходного списка. Чтобы продемонстрировать это, рассмотрим следующую реализацию:

let rec filter_map f = function
  | [] -> []
  | x :: xs -> match f x with
    | None -> xs
    | Some x -> x :: filter_map f xs

Здесь я сделал ошибку, вернув xs список ввода, когда f x оценивается как None. Другая ветвь строит выходной список, поэтому мы получили унифицированные типы входных и выходных списков. В правильной реализации вы должны рекурсивно вызывать filter_map в обеих ветвях,

let rec filter_map f = function
  | [] -> []
  | x :: xs -> match f x with
    | None -> filter_map f xs
    | Some x -> x :: filter_map f xs

Другие вопросы по теме