2016-11-13 47 views
2

考虑以下类型:ocaml的多态记录型较少一般

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 } 

我给了一个更新FORALL样类型定义。我的主要动机是因为updater会被事件调用。不知道事件会是什么。这可能是用户接口或按键等

问题上{ props; state = nextState; **updater** }updater定义中ocurring上点击:

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而不是与updaterlet newInstance? 我该如何解决这个问题?

回答

3

您正在做所谓的“多态递归”。这是一个递归函数,可以在每个递归循环的不同类型上调用。在你的情况下,它没有太多不同的类型,但将函数放入一个容器中。

多态递归已知是不可判定的推断,所以你需要通过使用polymorphic annotation来帮助typechecker一点点。在这种情况下,您还需要扩展实例功能(请参阅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 
    () 
+0

Muchas gracias! Ocaml比我想象的要困难得多:D – Seneca

+0

那么,你已经在类型层次上使用了相当先进的概念(一个forall)。我并不完全相信这真的是你应该使用的东西(很少有你真正想要的东西),但是我不知道相关的语义足以说真话。 – Drup

+0

是的,你是对的。 '事件发生在'Div.make〜onClick:(updater handleClick)'的语境中,并带有'let handleClick {props;州; updater} event =(* nextState *)'。我想我会制作一个活动类型,而不是通过它来完成。 – Seneca