Ocaml 不正确的类型推断
Ocaml incorrect type inference
我正在尝试制作 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))
我不明白的一件事是为什么编译器无法推断 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 有什么区别?
在我看来完全一样。如何进行此类型检查?
类型变量'_a
(实际字母无所谓,关键是下划线)是所谓的弱类型变量。这是一个不能泛化的变量,即它只能用一个具体类型代替。它就像一个可变值,但在类型领域。
用弱类型变量 '_a
表示的类型不包含在用泛型类型变量表示的类型中。而且,连编译单元都逃不掉,要么隐藏,要么具体化。
当表达式不是纯值(按语法定义)时,会创建弱类型变量。通常,它要么是一个功能应用程序,要么是一个抽象。当您通过枚举所有函数参数将部分应用函数替换为正常函数应用程序时,通常可以通过执行所谓的 eta 扩展来摆脱弱类型变量,即 updater = (fun props f i e -> mkUpdater props f i e)
.
我正在尝试制作 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))
我不明白的一件事是为什么编译器无法推断 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 有什么区别? 在我看来完全一样。如何进行此类型检查?
类型变量'_a
(实际字母无所谓,关键是下划线)是所谓的弱类型变量。这是一个不能泛化的变量,即它只能用一个具体类型代替。它就像一个可变值,但在类型领域。
用弱类型变量 '_a
表示的类型不包含在用泛型类型变量表示的类型中。而且,连编译单元都逃不掉,要么隐藏,要么具体化。
当表达式不是纯值(按语法定义)时,会创建弱类型变量。通常,它要么是一个功能应用程序,要么是一个抽象。当您通过枚举所有函数参数将部分应用函数替换为正常函数应用程序时,通常可以通过执行所谓的 eta 扩展来摆脱弱类型变量,即 updater = (fun props f i e -> mkUpdater props f i e)
.