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?
source to share
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
()
source to share