给出以下类型:
type ('props,'state) reactInstance =
{
props: 'props;
state: 'state;
updater:
'event .
(('props,'state) reactInstance -> 'event -> 'state) ->
('props,'state) reactInstance -> 'event -> unit;}
我试图实现:
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 }
我给了updater一个类似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
为什么会在let rec updater...
上updater
内发生这种情况,而在updater
中使用let newInstance
定义记录时却不会发生这种情况?
我该如何解决这个问题?
答案 0 :(得分:4)
您正在进行所谓的“多态递归”。这是一个递归函数,可以在每个递归循环中在不同类型上调用。在你的情况下,它没有太多不同的类型,但将功能放入带有forall的容器中。
众所周知,多态递归是不可判断的推断,所以你需要使用polymorphic annotation来帮助typechecker。在这种情况下,您还需要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
()