Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ocaml 具有泛型类型参数的多态变量的写入类型约束_Ocaml_Reason - Fatal编程技术网

Ocaml 具有泛型类型参数的多态变量的写入类型约束

Ocaml 具有泛型类型参数的多态变量的写入类型约束,ocaml,reason,Ocaml,Reason,背景:我正试图创建论文中描述的东西,但试图看看OCaml的多态性变体是否可以导致一个干净的RationalML实现 我这里的代码使用的是ReasonML语法,但这个问题同样适用于OCaml 首先,我为Val和Add定义了两个模块,这两个模块都实现了fmap——使它们成为haskel风格的函子 模块类型函子={ t型(a型); 设fmap:('a=>'b,t('a))=>t('b); }; 模块Val={ 类型t('e)=[Val(int)]; 让fmap=\uUQ=> 乐趣 |`Val(x)=>

背景:我正试图创建论文中描述的东西,但试图看看OCaml的多态性变体是否可以导致一个干净的RationalML实现

我这里的代码使用的是ReasonML语法,但这个问题同样适用于OCaml

首先,我为
Val
Add
定义了两个模块,这两个模块都实现了
fmap
——使它们成为haskel风格的函子

模块类型函子={
t型(a型);
设fmap:('a=>'b,t('a))=>t('b);
};
模块Val={
类型t('e)=[Val(int)];
让fmap=\uUQ=>
乐趣
|`Val(x)=>`Val(x);
};
模块添加={
类型t('e)=[|`Add('e,'e)];
设fmap=f=>
乐趣
|`Add(x,y)=>`Add((f(x),f(y)))
};
我可以相当容易地创建一个
代数
数据类型,将这两个模块组合成一个,并使用一个非常简单的
fmap
实现

模块代数={
类型t('t)=[Val.t('t)| Add.t('t)];
设fmap=(f,x)=>
开关(x){
|#Val.t as v=>Val.fmap(f,v)
|#Add.t as o=>Add.fmap(f,o)
};
};
这可以在更大的上下文中编译和工作,我可以计算由
Val
Add
值组成的表达式

然而,作为一名希望避免编写锅炉板代码的程序员,我的下一步将是创建一个函子(OCaml函子),该函子可以从任意两个兼容的模块生成这样的模块

我的第一次尝试是:

module join代数=(A1:函子,A2:函子)=>{
类型t('t)=[A1.t('t)| A2.t('t)];
设fmap=(f,x)=>
开关(x){
|#A1.t as v=>Val.fmap(f,v)
|#A2.t as o=>Add.fmap(f,o)
};
};
但这不起作用。由于
A1.t
A2.t
可以是任何东西,我不能将它们作为多态变体组合

错误:类型A1.t('t')不是多态变体类型

我尝试将类型约束添加到
Functor
模块类型:

模块类型函子={
类型t('a)='a约束[>]='a;
设fmap:('a=>'b,t('a))=>t('b);
};
模块Join代数=(A1:函子,A2:函子)=>{
类型t('t)=[A1.t('t)| A2.t('t)];//此行失败
}
现在我得到了编译器错误

错误:类型A1.t([>])不是多态变体类型

是否有任何方法可以创建一个基于这两个模块的模块函子


关于OCaml版本的说明:我正在使用bucklescript v。5,它使用OCAML4.02编译器。但是需要4.06的解决方案也是受欢迎的(Bucklescript应该支持)

您的
Functor
签名定义了一个抽象类型
'a t
。正如您正确指出的,“由于A1.t和A2.t可以是任何东西,我不能将它们组合为多态变量。”要解决
Functor
中的
'a t
是抽象的问题,您可以尝试通过以下操作使其成为多态变量:

module Functor=struct
键入'a t='a约束'a=[<]
结束
但是,
'a
类型变量不再代表包装值,而是多态变量约束。这肯定不是你想要的。您会得到错误
错误:类型A1.t([>])不是多态变体类型
,因为您只能将“精确变体类型”替换为多态变体:

第一种情况是一种完全不同的类型:所有可能的标签都是已知的,并且都有相关的类型,它们都可以存在。它的结构是众所周知的

在这三种情况下,标记可以直接以`标记名[类型xpr]的形式指定,也可以通过类型表达式间接指定,类型表达式必须扩展为一个精确的变体类型,其标记规范插入到相应的位置

()

您的
joinAlgenera
不需要多态变体。只要做:

模Join代数(A1:函子)(A2:函子)=struct
类型't t=t A1.t的左侧| t A2.t的右侧
设fmap fx=
将x与
|左v->左(A1.fmap f v)
|右o->右(A2.fmap f o)
结束
好处是
Functor
中的
'a t
保持抽象,代码适用于未定义多态变量的
Functor
模块