Ocaml polymorphic record type is less common

Given the following type:

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

      

I am trying to achieve:

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 }

      

I gave an update to the type definition of the type. My main motivation is that the update will be triggered by an event. I do not know what this event will be in advance. This could be a click on the UI or a key press, etc.

The problem arising inside the definition updater

on { 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

      

Why is this happening inside let rec updater...

on updater

and not when defining a record from updater

in let newInstance

? How do I get around this?

+2


source to share


1 answer


You are doing what is called "polymorphic recursion". It is a recursive function that can be called on a different type in each recursion loop. In your case, it's not a completely different type, but putting a function in a container with forall.

Polymorphic recursion is notoriously undecidable for inference, so you need to do a bit of help describing typechecker using polymorphic annotation . In this case, you also need to extend the instance function (see Ivg's other answer). Here is the final result. Note that your function is missing a parameter.



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
    ()

      

+3


source







All Articles