为什么在使用类型约束和类型类实例时这些类型不统一?

时间:2017-05-05 00:07:52

标签: purescript

所以,我正在尝试开发一个需要多态函数的函数。

我首先创建一个类Foo,以表示example函数中的约束类型参数。

module Test
where

class Foo a

此示例的随机类型......

newtype Bar = Bar Int

为了将Bar传递给任何具有Foo约束的东西,它需要有一个类型类,所以我这样做:

instance fooBar :: Foo Bar

一切都应该是完美的,但是,这不起作用,psc不认为类型统一,我不知道为什么:

example :: forall a. (Foo a) => (a -> Int) -> Int
example a = a (Bar 42)

错误如下:

Error found:
in module Test
at /Users/arahael/dev/foreign/test.purs line 11, column 16 - line 11, column 22

  Could not match type

    Bar

  with type

    a0


while checking that type Bar
  is at least as general as type a0
while checking that expression Bar 42
  has type a0
in value declaration example

where a0 is a rigid type variable
        bound at line 11, column 1 - line 11, column 22

See https://github.com/purescript/documentation/blob/master/errors/TypesDoNotUnify.md for more information,
or to contribute content related to this error.

1 个答案:

答案 0 :(得分:0)

比较

(1) example :: (forall a. (Foo a) => a -> Int) -> Int

(2) example :: forall a. (Foo a) => (a -> Int) -> Int

后者基本上对你(调用者)负责,以example作为参数提供一个函数(你的选择!)w /签名a -> Int(这样就有{{1} Foo)的实例。

另一方面,前者说,你,来电者,实际上并没有选择这个函数a。相反,正如Norman Ramsey在Haskell相关的stackoverflow回答here中解释的那样,当a -> Int是"在左边"箭头(而不是"在箭头&#34之上;)实现决定提供什么功能。 forall中的签名表示任何函数(2)都将作为a -> Int的参数(只要exampleFoo个。{ / p>

a只是"神奇地"然后,它起作用,因为编译器选择解包newtype (1)的函数是完全令人满意的,并且在Bar的情况下作为参数传递给example。毕竟,(1)的签名表明(1)应该返回相同的example值,无论给出Int函数(只要有a -> Int Foo } a的实例。在(2)的情况下,Int返回的example值可能会因所提供的特定函数a -> Int而异。编译器无法抓取任何它知道的随机满足类型的函数。它无法猜出调用者实际想到的aa -> Int的类型。