ocaml: почему указанный c тип не соответствует сигнатуре - PullRequest
1 голос
/ 15 апреля 2020

Я новичок и изо всех сил пытаюсь понять, что я делаю неправильно. Все указания приветствуются. У меня есть подпись

val input :
           arpv4:('a -> unit Lwt.t) ->
           ipv4:('a -> unit Lwt.t) ->
           ipv6:('a -> unit Lwt.t) ->
           ?decode:(Mirage_protocols.Ethernet.proto ->
                   Cstruct.t -> Mirage_protocols.Ethernet.proto * 'a) ->
           t -> Cstruct.t -> unit Lwt.t

Цель состоит в том, чтобы быть обобщенным c и отложить реализацию функций параметров. Если я реализую выражения, используя тип Cstruct.t, например,

...
   decode:(fun proto payload -> (proto, payload))

, я получаю ошибку

     Values do not match:
         val input :
           arpv4:(Cstruct.t -> unit Lwt.t) ->
           ipv4:(Cstruct.t -> unit Lwt.t) ->
           ipv6:(Cstruct.t -> unit Lwt.t) ->
           ?decode:(Mirage_protocols.Ethernet.proto ->
                   Cstruct.t -> Mirage_protocols.Ethernet.proto * Cstruct.t) ->
           t -> Cstruct.t -> unit Lwt.t
       is not included in
         val input :
           arpv4:('a -> unit Lwt.t) ->
           ipv4:('a -> unit Lwt.t) ->
           ipv6:('a -> unit Lwt.t) ->
           ?decode:(Mirage_protocols.Ethernet.proto ->
                   Cstruct.t -> Mirage_protocols.Ethernet.proto * 'a) ->
           t -> Cstruct.t -> unit Lwt.t

Я не понимаю, почему Cstruct.t не соответствует 'a. Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 17 апреля 2020

Как уже упоминалось, в ocaml переменная типа 'a,' b и т. Д. Означает «для всех типов, как определено компилятором». Простейшим случаем является функция тождества (функция, которая просто возвращает свой аргумент), которая может принимать и возвращать любой тип, и чей аргумент и тип возвращаемого значения могут поэтому обозначаться переменной типа 'a. Или список или массив может содержать любой тип, поэтому функции, возвращающие списки или массивы, могут иметь тип 'список или' массив.

Но многие проблемы не могут быть решены "для всех типов", а именно там, где код написано специфицируется c для определенного типа или конкретных типов. Как уже упоминалось, функция идентификации может принимать и возвращать любой тип. Но, например, функция, которая умножает свой аргумент на 2 и возвращает продукт, должна взять и вернуть число, либо int, либо float. Кроме того, в ocaml есть отдельные операторы для умножения чисел и чисел с плавающей запятой: поэтому, если вы хотите иметь функцию, которая работает как с числами, так и с числами с плавающей запятой, вы можете использовать числовой вариант и сопоставлять его, в этом случае вы не захотите не нужно полагаться на полиморфизм на уровне модуля - код будет мономорфным c для типа варианта.

Но в таком случае вы можете не захотеть иметь функцию, принимающую и / или возвращающую вариант , Возможно, вы захотите предоставить отдельные реализации для int и float и явно вызвать соответствующую версию. Вы можете сделать это с помощью интерфейсов модулей и реализации модулей. Функторы полезны при реализации этого как сокращение для написания специализированных модулей вручную.

Вы задали тот же вопрос на https://discuss.ocaml.org/t/why-doesnt-a-specific-type-fulfill-a/5525/6. Там вам предоставили пример такого полиморфизма на уровне модуля с использованием ограничения совместного использования:

module type Printable = sig
  type t
  val say : t -> unit
end

module Int_print: Printable with type t := int = struct
  let say i = Printf.printf "%d\n" i
end

module String_print: Printable with type t := string = struct
  let say s = Printf.printf "%s\n" s
end

let () =
  let open Int_print in
  say 20 ;
  let open String_print in
  say "hello again"

Ocaml не имеет полиморфизма ad ho c, в результате чего компилятор выберет, какой из них таких предоставленных пользователем альтернатив следует применять в каждом конкретном случае (известном как «перегрузка функций» в C ++ и аналогичных языках): в ocaml кодировщик должен сам заявить об этом, как в примере выше.

0 голосов
/ 15 апреля 2020

Когда на левой стороне стрелки появляется 'a, это означает, что функция принимает любой тип. Т.е. функция должна быть полиморфной c. Это не означает, что функция может принимать любой отдельный тип, это означает, что функция должна принимать все возможные типы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...