Cam*_*all 5 haskell types compiler-errors typeclass parametric-polymorphism
假设我有以下类型签名:
someFunction :: (Eq a, Eq b) => a -> b
Run Code Online (Sandbox Code Playgroud)
实施:
someFunction x = (2 :: Int)
Run Code Online (Sandbox Code Playgroud)
(不要把它放得太远,这只是一个例子).
我对签名的理解是" someFunction
接受一个作为Eq
类型类的实例的参数,并返回一个值(可以是不同类型),它是Eq
类型类的实例".Int
是一个实例Eq
,为什么GHC对这个实现感到不安?
这个错误很明显:
Run Code Online (Sandbox Code Playgroud)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
.使用这个函数的任何代码都应该只依赖于b
一个实例Eq
,对吧?在我看来,实现确实符合签名.我的实施怎么样打破了这个签名的期望?
Wil*_*ess 10
不,你的类型签名,实际上是
forall a b. (Eq a, Eq b) => a -> b
Run Code Online (Sandbox Code Playgroud)
表示您的函数必须可以使用任何类型调用,a
并且b
由调用站点确定,只要两者都是实例Eq
.
决定要返回的类型不是您的函数.这是你的功能用途决定了它.
所以你应该能够写作
let { i :: Int; i = 1;
n :: Integer; y :: Double;
n = foo i; -- foo :: Int -> Integer
y = foo i -- foo :: Int -> Double
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,您的函数的唯一实现是没有实现:
foo _ = x where {x = x}
Run Code Online (Sandbox Code Playgroud)
因为你无法产生任何你所要求的类型的价值.那种类型可以是任何东西,你无法了解它.
顺便说一下,其他类型类可能实际上允许你在这里定义一些东西,比如
foo :: (Enum a, Enum b, Bounded a, Bounded b) => a -> b
foo a = snd . last $ zip [minBound .. a] (cycle [minBound ..])
Run Code Online (Sandbox Code Playgroud)
我不是说这是一个明智的定义,只是有可能:
> foo () :: Bool
False
> foo True :: Int
-9223372036854775807
> foo (0 :: Int) :: Bool
Interrupted.
Run Code Online (Sandbox Code Playgroud)
对于来自更常用语言的程序员而言,这可能是一种常见的误解,认为这foo :: (Eq a) => a
意味着"我可以定义foo
返回我想要的任何类型,只要它在Eq
".它没有.:)
归档时间: |
|
查看次数: |
93 次 |
最近记录: |