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