为什么此实现无效?

时间:2018-10-22 08:04:45

标签: haskell types compiler-errors typeclass parametric-polymorphism

假设我具有以下类型签名:

someFunction :: (Eq a, Eq b) => a -> b

实现方式:

someFunction x = (2 :: Int)

(不要研究太多,这只是一个例子)。

我对签名的理解是“ someFunction接受一个作为Eq类型类的实例的参数,并返回一个值(可以是其他类型)。 Eq类型类”。 IntEq的实例,那么GHC为什么会对这种实现感到不满?

该错误使其很明显:

Couldn't match expected type ‘b’ with actual type ‘Int’
     ‘b’ is a rigid type variable bound by
       the type signature for:
         someFunction :: forall a b. (Eq a, Eq b) => a -> b

我想我不了解它必须“永久” b运行的要求。使用此功能的任何代码都应仅基于bEq实例的事实,对吗?在我看来,实现确实与签名匹配。那我的实现又违反了此签名的期望?

1 个答案:

答案 0 :(得分:10)

不,您的类型签名实际上是

forall a b. (Eq a, Eq b) => a -> b

表示您的函数必须可以由调用站点确定的任何类型ab进行调用,只要两者是Eq的实例。

决定返回哪种类型的不是您的函数。确定结果的是函数的 use

所以你应该能够写

    let { i :: Int; i = 1;
          n :: Integer; y :: Double;
          n = foo i;   -- foo :: Int -> Integer
          y = foo i    -- foo :: Int -> Double
        }

并且如您所见,该函数的唯一实现是 no 实现:

foo _ = x where {x = x}

因为您无法产生所需的 any 类型的值。这种类型可以是任何东西,而您对此一无所知。


通过 other 类型类实际上可以允许您在此处定义某物,例如

foo :: (Enum a, Enum b, Bounded a, Bounded b) => a -> b 
foo a = snd . last $ zip [minBound .. a] (cycle [minBound ..])

我并不是说这是一个明智的定义,只是可能:

> foo () :: Bool
False

> foo True :: Int
-9223372036854775807

> foo (0 :: Int) :: Bool
Interrupted.

对于来自较常用语言的程序员来说,普遍认为它是foo :: (Eq a) => a意味着“我可以定义foo来返回我想要的任何类型,只要它是{ {1}}”。没有。 :)