嗨,我是haskell编程的新手,我写了这段代码:
f :: a->Bool
f x = True
g :: a->Bool
g x = False
class P a where
func :: a->Bool
instance P Integer where
func x = f x
instance P Float where
func x = g x如果我以func Ghci的形式调用函数func 23.3,则返回以下错误:
<interactive>:6:6: Ambiguous type variable a0' in the constraints: (Fractional a0) arising from the literal 23.3' at <interactive>:6:6-9 (P a0) arising from a use of func' at <interactive>:6:1-4 Probable fix: add a type signature that fixes these type variable(s) In the first argument of func', namely 23.3' In the expression: func 23.3 In an equation for it': it = func 23.3
如果我以整数作为参数调用func,则代码可以正常工作。如果我将P的Float实例替换为Double实例,则代码将正确地用于调用func 23.3。为什么?
发布于 2013-12-20 22:10:48
这就是臭名昭著的摩诺主义限制。GHCi不知道具体将23.3转换为哪种类型,并且存在多种Fractional a数据类型(特别是Double和Float)。
您可以用
> :set -XNoMonomorphismRestriction或者更好
> func (23.3 :: Float)之所以如此,是因为文字23.3具有类型。
> :type 23.3
23.3 :: Fractional a => a而不是更具体的类型,如Float或Int。这实际上允许您实现自己的类型,这些类型可以由数字文本表示(有时是一个方便的技巧)。不幸的是,它给出了一个相当无用的错误信息,使大多数初学者感到困惑。但是编译器必须有特定的类型,因为您还可以添加
instance P Double where
func x = undefined然后,它必须决定将哪个func实例用于像23.3这样的文本。最好的做法是指定您使用的是内联类型,就像我在上面展示的那样。
它在GHCi中与Double一起工作的原因可能是因为GHCi有时会为了方便而试图将类型强制转换成更具体的东西。这就是为什么如果你要
> let x = [1..]
> :type x
x :: [Integer]相反,x应该具有(Enum a, Num a) => [a]类型。如果启用了单体主义限制(默认情况下),GHCi将尝试使类型与Integer、Double、IO一起工作,而不是Integral a => a、Double a => a或Monad m => m。但并不是每一种情况都很好。
https://stackoverflow.com/questions/20712679
复制相似问题