Haskell 为什么空列表上的函子合成返回显示错误?

Haskell 为什么空列表上的函子合成返回显示错误?,haskell,functor,Haskell,Functor,调用以下命令时,GHCI返回一个错误: 由于使用“print”而产生的不明确类型变量“f0”、“b0”会阻止解决约束“(Show(f0 b0))” 据我所知,这是因为我的表达式的类型是(numb,函子f)=>[fb],其中f是不明确的类型 但是,List的Functor实例将fmap定义为map,如果第二个参数为[],则map的定义将忽略函数参数,以简单地返回[]。这意味着无论我应用了多少fmap合成,我的表达式都应该返回[],并且show[]的调用应该通过。为什么我看到了错误呢 (fmap.f

调用以下命令时,GHCI返回一个错误: 由于使用“print”而产生的不明确类型变量“f0”、“b0”会阻止解决约束“(Show(f0 b0))”

据我所知,这是因为我的表达式的类型是(numb,函子f)=>[fb],其中f是不明确的类型

但是,List的Functor实例将fmap定义为map,如果第二个参数为[],则map的定义将忽略函数参数,以简单地返回[]。这意味着无论我应用了多少fmap合成,我的表达式都应该返回[],并且show[]的调用应该通过。为什么我看到了错误呢

(fmap.fmap)(+1)[]

确实,您的函数将始终返回
[]
,但是类型类分派(发生在编译时而不是运行时)必须基于要显示的参数类型。
[a]
Show
实例要求也解析
Show a
实例Show a=>Show[a]
)——因为有许多类型的
[a]
的值确实包含元素,而且由于列表元素的类型(全部0个)不明确,无法解析
Show
约束

这可能会导致您问为什么
show[]
例如没有相同的问题,因为
[]:[a]
。这里的答案是,GHCi有一些特殊的启发法,适用于某些简单的情况,以使在提示下工作更愉快。如果
:set-xnoextendededefaultrules
可以看到
show[]
将具有相同的行为。在您的情况下,由于列表的元素类型是
f0 b0
而不是单个类型变量,因此链接的扩展默认规则不适用,因此列表元素类型仍然包含不明确的类型变量


您可以通过自己解决一些类型约束(比如使用
-XTypeApplications
)来发现这是一个问题。即使解决
Functor
约束也足以使正常的Haskell类型默认规则再次适用:
(fmap.(fmap@[])(+1)[]
确实会在GHCi提示符下打印
[]

确实,您的函数将始终返回
[]
,但是类型类调度(发生在编译时,而不是运行时)必须基于
show
的参数类型。
[a]
show
实例要求也解析
show a
实例show a=>show[a]
),因为有许多
[a]类型的值
其中确实包含元素---并且由于列表元素的类型(全部为0)不明确,因此无法解析
Show
约束

这可能会导致您问为什么
show[]
例如没有相同的问题,因为
[]:[a]
。这里的答案是,GHCi有一些特殊的启发式方法,适用于某些简单的情况,以便使在提示下工作更愉快。如果您
:set-xnoextendeddedfaultrules
可以看到
show[]
将具有相同的行为。在您的情况下,由于列表的元素类型是
f0 b0
而不是单个类型变量,因此链接的扩展默认规则不适用,因此列表元素类型仍然包含不明确的类型变量


您可以通过自己解决一些类型约束(例如使用
-XTypeApplications
)来发现这是一个问题。即使解决
Functor
约束也足以使正常的Haskell类型默认规则再次适用:
(fmap.(fmap@[])(+1)[
确实打印
[]
在GHCi提示符下。

因为为了呈现列表,类型约束是它应该呈现元素。实例是
instance Show a=>Show[a]
。谢谢,这是有意义的。这是否意味着如果我要写一个函数functorExample::[[Int]]->[[Int]],其中functorExample=(fmap.fmap)(+1),不明确的类型f0和a0被解析为有效的实例,即[]和Int?实际上,您可以尝试
(fmap.fmap)(+1)[]:[[Int]]
,它将打印
[]
。因为为了呈现列表,类型约束是它应该呈现元素。实例是
实例Show a=>Show[a]
。谢谢,这很有意义。这是否意味着如果我要编写一个函数functorExample::[[Int]]->[[Int]],其中functorExample=(fmap.fmap)(+1),不明确的类型f0和a0将被解析为有效的实例,即[]和Int?实际上,您可以尝试
(fmap.fmap)(+1)]:[[Int]]
,它将打印
[]