ReasonML签名不匹配

时间:2019-07-23 05:16:33

标签: types ocaml reason bucklescript

我在我定义的解析为我期望的type mutationFunctionType = (~id: UUID.t, ~classroomId: UUID.t, unit) => unit;'a的类型之间在ReasonML中遇到签名不匹配的问题。 (如下所示)。

[1]   Signature mismatch:
[1]   ...
[1]   Values do not match:
[1]     let callMutationWithApollo:
[1]       ApolloMutation.apolloMutationType(Config.t) => mutationFunctionType
[1]   is not included in
[1]     let callMutationWithApollo:
[1]       ApolloMutation.apolloMutationType(Config.t) => 'a

我很好奇为什么会收到此错误,因为我认为多态类型`a基本上可以视为任何类型。

谢谢

2 个答案:

答案 0 :(得分:3)

类型多态性允许您以某些类型通用地编写函数。 例如,多态身份具有类型'a => 'a。 这意味着可以通过实例化int => intbool => bool'a类型使用它。

但是,此'a并不表示任何事情。它仅在一个方向上起作用: 'a可以成为任何事物,但是任何事物都不能成为'a。 因此,您确实可以从ApolloMutation.apolloMutationType(Config.t) => 'a获得 ApolloMutation.apolloMutationType(Config.t) => mutationFunctionType,但您所做的却恰恰相反。

例如,您不能将int => int函数转换为int => 'a函数。 顺便说一句,除非返回错误或不终止,否则实际上不可能提供类型int => 'aApolloMutation.apolloMutationType(Config.t) => 'a的功能。因此,我建议您尽可能更新签名,以明确提及mutationFunctionType

答案 1 :(得分:1)

  

我很好奇为什么会收到此错误,因为我认为多态类型`a基本上可以视为任何类型。

是的,你是对的,'a意味着任何东西。但是成为什么到底意味着什么?值的类型定义了可以在哪个上下文中使用该值。例如,如果您的值的类型为int,则可以在需要int或''a的任何地方使用它。说您的函数具有类型'a意味着您可以使用函数代替intunit或任何其他函数。实际上,类型“ a”表示可以使用该值代替任何其他值。

用不同的方式表示您的签名中的函数类型是您的合同。并且您通过说您的功能可以在任何地方使用来使自己过度负担。而且类型检查器说您不正确-您的函数仅适用于非常特殊的上下文

ApolloMutation.apolloMutationType(Config.t) => mutationFunctionType

它甚至不是多态的(即,您的函数不可能适合多种类型-它是 monomorphic ,即只有一种类型)。

但是,在一个特定的上下文中,使用'a的意思是“我不在乎,选择所需的任何类型”,这是在您指定类型约束,即当您在let绑定中注释函数的参数或变量时,例如,这里'a

 let sum = (x, y): 'a => x + y;

表示“任何类型”,尽管事实上它是int并且只有int

当您提供注释(又称类型约束)时,它由typecheker添加为类型方程式的附加约束,例如

 let pair: ('a, 'a) => ('a, 'a) = (x, y) => (x, y);

在这里,函数pair被约束为两个相等的对(unifiable 1 )类型的对,但是这些类型可以是任何东西,只需要它们相等即可。如果我们不添加此约束,则函数的类型将为('a,'b) => ('a,'b),这是更通用的。


1)实际上,它们不必相等,这种约束只是说xy必须统一,通常在单态类型的情况下这意味着它们应该相等,例如int仅与int不可兼而有之,但是对于多型类型,尤其是对于子类型,将推断出最小上限,但这是一个完全不同的故事。