【发布时间】:2015-04-22 02:25:27
【问题描述】:
给定以下代码:
import Data.Word
data T = T deriving (Eq, Show)
class C a where f :: a -> ()
instance C T where f _ = ()
instance C Word16 where f _ = ()
main = return $ f 0x16
GHC 抱怨它无法推断文字 0x16 的类型应该是什么错误:
No instance for (Num a0) arising from the literal ‘22’
The type variable ‘a0’ is ambiguous
很容易看出为什么会这样——Haskell 允许数字文字是具有Num 实例的任何类型,在这里我们不能区分文字 0x16 的类型(或22) 应该是。
作为人类阅读我打算做的事情也很清楚——只有一个满足Num约束的C类的可用实例,所以显然我打算使用那个0x16应该被视为Word16。
我知道有两种方法可以修复它:要么用它的类型注释文字:
main = return $ f (0x16 :: Word16)
或定义一个本质上为您执行该注释的函数:
w16 x = x :: Word16
main = return $ f (w16 0x16)
我尝试了第三种方法,将 default (Word16) 粘贴在文件顶部,希望 Haskell 会选择它作为数字文字的默认类型,但我想我误解了 default 关键字是什么应该这样做,因为那不起作用。
我知道类型类是开放的,所以只是因为您可以在上面引用的上下文中假设Word16 是C 的唯一数字实例,它可能不包含在其他模块中。但我的问题是:是否有某种机制可以让我假设/强制执行该属性,以便可以使用 f 并让 Haskell 将其数字参数的类型解析为 Word16,而无需在调用站点进行显式注释?
上下文是我正在实现 EDSL,当我知道我的参数将是 Word16 或其他一些非数字类型时,我宁愿不必包含手动类型提示。如果它使 EDSL 感觉更自然,我愿意接受一些肮脏的类型/扩展滥用!虽然如果解决方案确实涉及顽皮的编译指示,我肯定会很感激提示我在使用它们时应该注意什么。
【问题讨论】:
标签: haskell typeclass ambiguity ambiguous