为什么空白列表上的仿函数组合会返回显示错误?

use*_*132 1 haskell functor

调用以下命令时,GHCI返回错误:使用“ print”引起的含糊类型变量“ f0”,“ b0”阻止解决约束“(Show(f0 b0))”。

据我了解,这是因为表达式的类型是(Num b,Functor f)=> [fb],其中f是模棱两可的类型。

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

(fmap.fmap) (+1) []
Run Code Online (Sandbox Code Playgroud)

Pet*_*don 5

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

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

您可以自己解决一些类型约束,例如使用来查看问题所在-XTypeApplications。即使解决了Functor约束也足以使普通的Haskell类型默认规则再次适用:(fmap.(fmap @[])) (+1) []确实会[]在GHCi提示符下打印。