Haskell 错误 - 未解决的重载 - 因使用“print”而产生的类型变量“a0”不明确
Haskell ERROR - Unresolved overloading - Ambiguous type variable `a0' arising from a use of `print'
此问题基于“Haskell 从第一原则开始编程”一书中的示例。在关于类型类的章节中,展示了一个不正确的例子。我正在努力让它发挥作用:
class Numberish a where
fromNumber :: Integer -> a
toNumber :: a -> Integer
newtype Age =
Age Integer
deriving (Eq, Show)
instance Numberish Age where
fromNumber n = Age n
toNumber (Age n) = n
toNumber 函数有效,但fromNumber 无效。我使用 HUGS 时的错误是“错误 - 未解决的重载”。当我使用 GHCi 时,错误以“使用 'print' 引起的不明确类型变量 'a0' 阻止约束 '(Show a0)' 被解决”开始。
我尝试更改新类型并直接重新声明实例(并仅使用 deriving Eq
而不是同时使用 Eq 和 Show),但同样的错误再次出现:
newtype Age a =
Age Integer
deriving Eq
instance Show (Age a) where
show (Age a) = "Age " ++ show a
instance Show a => Numberish (Age a) where
fromNumber n = Age n
toNumber (Age n) = n
有没有办法让 fromNumber 起作用?比如我们输入fromNumber 1
,输出应该是Age 1
.
根据最新的答案,我根据我更改的代码尝试了 GHCi 中的新输入,并截屏了结果。 fromNumber 42 :: Age String
有效。
我也在基于原始示例代码的 GHCi 中尝试了 fromNumber 42 :: Age
,它也有效。
在第一个示例中,问题出在表达式中的类型
fromNumber 5
GHCi 只知道结果类型是 Numberish
的某个实例,但它不知道是哪一个。它只有一个可供选择这一事实并不重要。
你可以告诉 GHCi 使用哪种类型,它会很高兴:
fromNumber 5 :: Age
如果您在实际程序中使用它,很可能会有其他东西告诉编译器它是哪种类型;你会用这个值做其他特定于年龄的事情,比如将它存储在记录中或将它作为参数传递给函数。在这种情况下会出现问题,因为该值未用于任何用途,因此编译器无法缩小范围。
第二部分的代码不太清楚;您给了 Age
一个未使用的类型参数。这称为 phantom type,我不确定您是否打算这样做。当您出于某些其他原因而不是了解内容而想要使用类型标记值时,将使用这些。所以第二个版本 fromNumber 42 :: Age String
应该可以工作,因为 String
有一个 Show
实例,正如你的 Numberish
实例所需要的。
此问题基于“Haskell 从第一原则开始编程”一书中的示例。在关于类型类的章节中,展示了一个不正确的例子。我正在努力让它发挥作用:
class Numberish a where
fromNumber :: Integer -> a
toNumber :: a -> Integer
newtype Age =
Age Integer
deriving (Eq, Show)
instance Numberish Age where
fromNumber n = Age n
toNumber (Age n) = n
toNumber 函数有效,但fromNumber 无效。我使用 HUGS 时的错误是“错误 - 未解决的重载”。当我使用 GHCi 时,错误以“使用 'print' 引起的不明确类型变量 'a0' 阻止约束 '(Show a0)' 被解决”开始。
我尝试更改新类型并直接重新声明实例(并仅使用 deriving Eq
而不是同时使用 Eq 和 Show),但同样的错误再次出现:
newtype Age a =
Age Integer
deriving Eq
instance Show (Age a) where
show (Age a) = "Age " ++ show a
instance Show a => Numberish (Age a) where
fromNumber n = Age n
toNumber (Age n) = n
有没有办法让 fromNumber 起作用?比如我们输入fromNumber 1
,输出应该是Age 1
.
根据最新的答案,我根据我更改的代码尝试了 GHCi 中的新输入,并截屏了结果。 fromNumber 42 :: Age String
有效。
我也在基于原始示例代码的 GHCi 中尝试了 fromNumber 42 :: Age
,它也有效。
在第一个示例中,问题出在表达式中的类型
fromNumber 5
GHCi 只知道结果类型是 Numberish
的某个实例,但它不知道是哪一个。它只有一个可供选择这一事实并不重要。
你可以告诉 GHCi 使用哪种类型,它会很高兴:
fromNumber 5 :: Age
如果您在实际程序中使用它,很可能会有其他东西告诉编译器它是哪种类型;你会用这个值做其他特定于年龄的事情,比如将它存储在记录中或将它作为参数传递给函数。在这种情况下会出现问题,因为该值未用于任何用途,因此编译器无法缩小范围。
第二部分的代码不太清楚;您给了 Age
一个未使用的类型参数。这称为 phantom type,我不确定您是否打算这样做。当您出于某些其他原因而不是了解内容而想要使用类型标记值时,将使用这些。所以第二个版本 fromNumber 42 :: Age String
应该可以工作,因为 String
有一个 Show
实例,正如你的 Numberish
实例所需要的。