本文介绍了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的类型定义.我的主要动机是因为更新程序将与事件一起被调用.不知道那件事会事先发生.可以单击用户界面或按键等.

I gave the updater a forall-like type definition. My main motivation is because the updater will get invoked with an event. No idea what that event will be beforehand. It could be a click on the user interface or key press etc.

{ props; state = nextState; **updater** }updater定义内出现的问题:

The problem ocurring inside the updater definition on { 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

为什么在updaterlet rec updater...内部而不是在let newInstance中用updater定义记录时会发生这种情况?我该如何解决?

Why does this occur inside the let rec updater... on updater and not when defining the record with updater in let newInstance? How do I get around this?

推荐答案

您正在执行所谓的多态递归".这是一个递归函数,可以在每个递归循环上以不同的类型调用它.在您的情况下,它的类型没有太大不同,但是将功能放进一个容器中.

You are doing what is called "polymorphic recursion". This is a recursive function that could be invoked on different type at each recursion loop. In your case, it's not much different type, but putting the function into a container with a forall.

众所周知,多态递归无法确定,因此您需要使用多态注释.在这种情况下,您还需要eta扩展实例函数(请参阅ivg的其他答案).这是最终结果.请注意,您的函数缺少参数.

Polymorphic recursion is known to be undecidable to infer, so you need to help the typechecker a bit by using polymorphic annotation. In this case, you also need to eta expand the instance function (see ivg's other answer). Here is the final result. Note that your function was missing a parameter.

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
    ()

这篇关于Ocaml多态记录类型不太通用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-16 01:05