dune utop 和 utop 的区别

difference between dune utop and utop

如果我在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 加载包含此代码的库作为 file/module,我收到以下错误:

~$ 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 文件中无效

Edit :简单的解决方案是添加一个 closed 类型注释。

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

我不确定为什么交互式会话和 dune utop lib 一次性加载的行为应该不同

你的类型前面有 _,这表明你的类型是 weakly polymorphic,编译器拒绝让这些东西存在于编译对象中。

你可以用 mwe 得到相同的结果:

let store = ref None

顶层是可以的,因为它可以稍后解析为单态类型,如果你评估类似 store:= Some1 的东西,"monomorphise" 类型从 _a option refint option ref