为什么这个实现无效?

Why is this implementation invalid?

假设我有以下类型签名:

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

实施中:

someFunction x = (2 :: Int)

(不用深究,只是举个例子)

我对签名的理解是“someFunction 接受一个参数,该参数是 Eq 类型类的一个实例,returns 一个值(可以是不同的类型) 是 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

我想我不明白的是它工作的要求 "forall" b。任何使用此函数的代码都应该只依赖于 bEq 的实例这一事实,对吗?在我看来,实现确实与签名匹配。我的实现是否违反了此签名的预期?

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

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

意味着您的函数必须可以使用 任何 类型 ab 调用,由 调用站点,只要两者都是 Eq.

的实例

决定 return 类型的不是您的函数。 决定该类型的是您函数的 use

所以你应该可以写

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

如您所见,您函数的唯一实现是实现:

foo _ = x where {x = x}

因为您无法生成您需要的 any 类型的值。该类型可以是任何类型,而您无法了解它的任何信息。


顺便说一句 other 类型类实际上可能允许您在这里定义 something,比如

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 意味着 "I get to define foo to return any type I want, as long as it is in Eq" 可能是一个常见的误解。它没有。 :)