我试图将一个打字版本的React作为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))
我不明白的一件事是编译器无法推断updater = (mkUpdater props)
中let newInstance = { props; state = nextState; 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和'之间的区别是什么? 它看起来与我完全相同。如何进行此类检查?
答案 0 :(得分:2)
类型变量'_a
(实际字母无关紧要,关键是下划线)是一个所谓的弱类型变量。这是一个不能概括的变量,即它只能用一种具体的类型代替。它就像一个可变的值,但在类型的领域。
用弱类型变量'_a
表示的类型不包含在用泛型类型变量表示的类型中。而且,它甚至无法逃脱编译单元,应该隐藏或具体化。
当表达式不是纯值(在语法上定义)时,会创建弱类型变量。通常,它是功能应用程序或抽象。当您通过枚举所有函数参数(即updater = (fun props f i e -> mkUpdater props f i e)
)将部分应用的函数替换为正常函数应用程序时,通常可以通过执行所谓的eta-expansion来消除弱类型变量。