Ocaml 多态记录类型不太通用

Sen*_*eca 2 polymorphism ocaml

给定以下类型:

 type ('props,'state) reactInstance =
  {
  props: 'props;
  state: 'state;
  updater:
    'event .
      (('props,'state) reactInstance -> 'event -> 'state) ->
        ('props,'state) reactInstance -> 'event -> unit;}
Run Code Online (Sandbox Code Playgroud)

我正在努力实现:

let rec updater f instance event =
  let nextState = f instance event in
  let newInstance =
    { props; state = nextState; updater } in
  ()

let newInstance =
  { props; state = (reactClass.getInitialState ()); updater }
Run Code Online (Sandbox Code Playgroud)

我给了更新程序一个类似 forall 的类型定义。我的主要动机是因为更新程序将被事件调用。事先不知道该事件会是什么。它可以是用户界面上的点击或按键等。

updater定义中出现的问题{ props; state = nextState; **updater** }

Error: This field value has type
         (React.reactInstance props#1618 state#1200 => 'a => state#1200) =>
React.reactInstance props#1618 state#1200 => 'a => unit
       which is less general than
         'event.
  (React.reactInstance 'props 'state => 'event => 'state) =>
  React.reactInstance 'props 'state => 'event => unit
Run Code Online (Sandbox Code Playgroud)

为什么这种情况发生在let rec updater...on内部,而不是在使用inupdater 定义记录时发生?我该如何解决这个问题?updaterlet newInstance

Dru*_*rup 5

您正在做所谓的“多态递归”。这是一个递归函数,可以在每个递归循环中对不同类型进行调用。就您而言,它的类型没有太大不同,但将函数放入带有 forall 的容器中。

众所周知,多态递归是无法确定的推断,因此您需要通过使用多态注释来帮助类型检查器。在这种情况下,还需要eta扩展实例函数(参见ivg的其他答案)。这是最终结果。请注意,您的函数缺少参数。

type ('props,'state) reactInstance = {
  props: 'props;
  state: 'state;
  updater:
    'event .
      (('props,'state) reactInstance -> 'event -> 'state) ->
    ('props,'state) reactInstance -> 'event -> unit;}

let rec updater
  : 'event .
    'props ->
    (('props,'state) reactInstance -> 'event -> 'state) ->
    ('props,'state) reactInstance -> 'event -> unit
  = fun props f instance event ->
    let nextUpdater f i e = updater props f i e in
    let nextState = f instance event in
    let newInstance =
      { props; state = nextState; updater = nextUpdater } in
    ()
Run Code Online (Sandbox Code Playgroud)