为什么这个实现无效?
Why is this implementation invalid?
假设我有以下类型签名:
someFunction :: (Eq a, Eq b) => a -> b
实施中:
someFunction x = (2 :: Int)
(不用深究,只是举个例子)
我对签名的理解是“someFunction
接受一个参数,该参数是 Eq
类型类的一个实例,returns 一个值(可以是不同的类型) 是 Eq
类型类的一个实例”。 Int
是 Eq
的一个实例,那么为什么 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
。任何使用此函数的代码都应该只依赖于 b
是 Eq
的实例这一事实,对吗?在我看来,实现确实与签名匹配。我的实现是否违反了此签名的预期?
不,你的类型签名,实际上是
forall a b. (Eq a, Eq b) => a -> b
意味着您的函数必须可以使用 任何 类型 a
和 b
调用,由 调用站点,只要两者都是 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
" 可能是一个常见的误解。它没有。 :)
假设我有以下类型签名:
someFunction :: (Eq a, Eq b) => a -> b
实施中:
someFunction x = (2 :: Int)
(不用深究,只是举个例子)
我对签名的理解是“someFunction
接受一个参数,该参数是 Eq
类型类的一个实例,returns 一个值(可以是不同的类型) 是 Eq
类型类的一个实例”。 Int
是 Eq
的一个实例,那么为什么 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
。任何使用此函数的代码都应该只依赖于 b
是 Eq
的实例这一事实,对吗?在我看来,实现确实与签名匹配。我的实现是否违反了此签名的预期?
不,你的类型签名,实际上是
forall a b. (Eq a, Eq b) => a -> b
意味着您的函数必须可以使用 任何 类型 a
和 b
调用,由 调用站点,只要两者都是 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
" 可能是一个常见的误解。它没有。 :)