2016-11-12 56 views
2

我正在尝试在Ocaml中作为练习的打字版本。 为了使它更实用,我将一条记录作为参数传递给渲染。Ocaml不正确的类型推断

type ('props,'state) reactInstance = 
    { 
    props: 'props; 
    state: 'state; 
    updater: 'a . ('props,'state) reactInstance -> 'a -> 'state -> unit;} 
and ('props,'state) reactClass = 
    { 
    getInitialState: unit -> 'state; 
    render: ('props,'state) reactInstance -> element;} 

module type ComponentBluePrint = 
    sig 
    type props 
    type state 
    val getInitialState : unit -> state 
    val render : (props,state) reactInstance -> element 
    end 

module type ReactClass = 
    sig 
    type props 
    type state 
    val mkUpdater : 
    props -> 
    ((props,state) reactInstance -> 'e -> state) -> 
     (props,state) reactInstance -> 'e -> unit 
    val reactClass : (props,state) reactClass 
    end 

module CreateComponent(M:ComponentBluePrint) = 
    (struct 
    include M 
    let rec mkUpdater props f i e = 
     let nextState = f i e in 
     let newInstance = 
     { props; state = nextState; updater = (mkUpdater props) } in 
     () 

    let reactClass = 
     { render = M.render; getInitialState = M.getInitialState } 
    end : (ReactClass with type props = M.props and type state = M.state)) 

有一件事我不明白的是为什么编译器不能在let newInstance = { props; state = nextState; updater = (mkUpdater props) }推断updater = (mkUpdater props)类型。

Error: Signature mismatch: 
     Values do not match: 
     let mkUpdater : 
    props => 
    (reactInstance props state => '_a => '_b) => 
    reactInstance props state => '_a => unit 
     is not included in 
     let mkUpdater : 
    props => 
    (reactInstance props state => 'e => state) => 
    reactInstance props state => 'e => unit 

'_a和'e有什么区别? 它看起来和我完全一样。我如何进行这种类型的检查?

+0

您提供的错误不是您的文件生成的实际错误。正确的错误是“错误:该表达式具有类型('a - >'b - >'c) - >'a - >'b - >'d 但是期望表达式为 ('e,'c )reactInstance - >'f - >'c - >单元 类型'a - >'b - >'c与类型不兼容('e,'c)reactInstance “ – Drup

+0

有很多事情看起来像错误该文件,但如果不知道操作的假定语义如何,很难解决它们。然而,跳到我的第一件事是更新器领域的''a。',你确定你想在这里使用吗?这看起来不太有用。 – Drup

回答

2

一个类型变量'_a(实际的字母并不重要,关键的是下划线)是一个所谓的弱类型变量。这是一个不能概括的变量,也就是说,它只能被一个具体类型替代。这就像一个可变的价值,但在类型领域。

用弱类型变量'_a表示的类型不包含在用泛型类型变量表示的类型中。而且,它甚至无法逃脱编制单位,应该隐藏或具体化。

当表达式不是纯值(在语法上定义)时会创建弱类型变量。通常,它是一个函数应用程序或抽象。当通过枚举所有函数参数(即updater = (fun props f i e -> mkUpdater props f i e))将部分应用函数替换为普通函数应用程序时,通常可以通过执行所谓的eta-expansion来摆脱弱类型变量。

+0

感谢您的好解释! – Seneca