haskell - 为什么这个实现无效?
问题描述
假设我有以下类型签名:
someFunction :: (Eq a, Eq b) => a -> b
通过实施:
someFunction x = (2 :: Int)
(不要看得太远,这只是一个例子)。
我对签名的理解是“someFunction
接受一个作为类型类实例的参数Eq
,并返回一个作为类型类实例的值(可以是不同类型)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
.
决定返回什么类型的不是你的函数。这是您的功能的使用决定了这一点。
所以你应该可以写
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}
因为你无法产生任何需要你的类型的值。这种类型可以是任何东西,你无法知道任何关于它的东西。
顺便说一句,其他类型类实际上可能允许你在这里定义一些东西,比如
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
返回任何我想要的类型,只要它在Eq
”中,这可能是一个常见的误解。它没有。:)
推荐阅读
- css - 我正在应用 transform: scale(2) 使网站与视障人士兼容。当我进行转换时:scale(2),
- rest - 休息端点认证响应
- html - 如何为表格单元格添加固定高度?
- r - R Shiny 错误与 rbind 编译循环结果:错误评估嵌套太深:无限递归
- javascript - 如何在单击按钮并按 Enter 时启动 jquery 功能
- kubernetes - 仅允许使用证书访问命名空间
- reactjs - React + Material UI 表格分页未正确显示
- html - 如何使用css创建均匀分布的垂直线作为背景?
- c++ - 智能指针基础
- model-view-controller - View如何更新Model?