разница между утопой утопом и утопом - PullRequest
0 голосов
/ 10 ноября 2018

Если я загружаю следующий код в utop, после #require "mparser", он принимается на верхнем уровне и дает подпись ниже

open MParser

let infix p op = Infix (p |>> (fun _ a b -> (`Binop (op, a, b))), Assoc_left)

let operators =
  [
    [
      infix (char '*') `Mul;
      infix (char '/') `Div;
    ];
    [
      infix (char '+') `Add;
      infix (char '-') `Sub;
    ];
  ]

let decimal = many1_chars digit |>> int_of_string

let term = (decimal |>> fun i -> `Int i)
let expr s  =  expression operators term s

let rec calc = function
  | `Int i -> i
  | `Binop (op, a, b) ->
      match op with
        | `Add -> calc a + calc b
        | `Sub -> calc a - calc b
        | `Mul -> calc a * calc b
        | `Div -> calc a / calc b

принято utop как

val infix :
  ('a, 'b) MParser.t ->
  'c -> ([> `Binop of 'c * 'd * 'd ] as 'd, 'b) MParser.operator = <fun>
val operators :
  (_[> `Binop of _[> `Add | `Div | `Mul | `Sub ] * 'a * 'a | `Int of int ]
   as 'a, unit)
  MParser.operator list list =
  [[Infix (<fun>, Assoc_left); Infix (<fun>, Assoc_left)];
   [Infix (<fun>, Assoc_left); Infix (<fun>, Assoc_left)]]
val decimal : (int, unit) MParser.t = <fun>
val term : ([> `Int of int ], unit) MParser.t = <fun>
val expr :
  unit MParser.state ->
  (_[> `Binop of _[> `Add | `Div | `Mul | `Sub ] * 'a * 'a | `Int of int ]
   as 'a, unit)
  MParser.reply = <fun>
val calc :
  ([< `Binop of [< `Add | `Div | `Mul | `Sub ] * 'a * 'a | `Int of int ] as 'a) ->
  int = <fun>

Теперь, если я попытаюсь загрузить dune utop библиотеку, содержащую этот код в виде файла / модуля, я получу следующую ошибку:

~$ dune utop lib
      ocamlc lib/.lib.objs/lib__VariantExemple.{cmi,cmo,cmt} (exit 2)
(cd _build/default && /usr/local/bin/ocamlc.opt -w @a-4-29-40-41-42-44-45-48-58-59-60-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -bin-annot -I lib/.lib.objs -I lib/.lib.objs/.private -I /Users/nrolland/.opam/system/lib/bytes -I /Users/nrolland/.opam/system/lib/mparser -I /Users/nrolland/.opam/system/lib/re -I /Users/nrolland/.opam/system/lib/re/perl -I /Users/nrolland/.opam/system/lib/seq -no-alias-deps -opaque -open Lib -o lib/.lib.objs/lib__VariantExemple.cmo -c -impl lib/variantExemple.ml)
File "lib/variantExemple.ml", line 5, characters 4-13:
Error: The type of this expression,
       (_[> `Binop of _[> `Add | `Div | `Mul | `Sub ] * 'a * 'a | `Int of int ]
        as 'a, '_weak1)
       operator list list, contains type variables that cannot be generalized

Похоже, что отсутствуют некоторые аннотации типов. Я не слишком знаком с полиморфным типом варианта и есть ли очевидное решение?

Я надеялся, что вставка части подписи, заданной utop в интерфейсе, сработает, но, похоже, она недопустима в .mli файле

Редактировать : простое решение - добавить аннотацию типа закрытый .

let operators : ([ `Binop of [ `Add | `Div | `Mul | `Sub ] * 'a * 'a | `Int of int ] as 'a, unit) operator list list  =

Я не уверен, есть ли причина, по которой интерактивный сеанс и dune utop lib однократная загрузка должны вести себя по-разному

1 Ответ

0 голосов
/ 12 ноября 2018

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

Вы можете получить тот же результат с Mwe:

let store = ref None

Верхний уровень в порядке с этим, так как он может быть преобразован в мономорфный тип позже, если вы оцениваете что-то вроде store:= Some1, которое "мономорфизирует" тип от _a option ref до int option ref

...