我有以下无法编译的代码段:
{-# LANGUAGE OverloadedStrings, TypeFamilies, MultiParamTypeClasses #-}
module Main where
class Add a b where
type SumTy a b
plus :: a -> b -> SumTy a b
instance Add Integer Double where
type SumTy Integer Double = Double
plus x y = fromIntegral x + y
instance Add Double Integer where
type SumTy Double Integer = Double
plus x y = x + fromIntegral y
main :: IO ()
main = do
print $ plus (5::Integer) 6
print $ plus (5.0::Double) 6.0
错误消息是:
app/Main.hs:25:3: error:
• Ambiguous type variable ‘b1’ arising from a use of ‘print’
prevents the constraint ‘(Show
(SumTy Integer b1))’ from being solved.
Probable fix: use a type annotation to specify what ‘b1’ should be.
These potential instances exist:
instance Show BS.ByteString
-- Defined in ‘Data.ByteString.Internal’
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
...plus 24 others
...plus 22 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of a 'do' block: print $ plus (5 :: Integer) 6
In the expression:
do print $ plus (5 :: Integer) 6
print $ plus (5.0 :: Double) 6.0
In an equation for ‘main’:
main
= do print $ plus (5 :: Integer) 6
print $ plus (5.0 :: Double) 6.0
|
25 | print $ plus (5::Integer) 6
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
使用“打印”产生的歧义类型变量“ b1”是什么意思?我看不到b1
的任何地方。
答案 0 :(得分:4)
plus (5::Integer) 6
第一个参数的类型为Integer
。第二个数字的类型可以是任何数字类型,我们假设b1
为Num b1
。因此,我们正在调用该函数
plus :: Integer -> b1 -> SumTy Integer b1
,但是周围没有匹配的实例。 Add Integer Double
只有一个实例,但是我们不能调用该实例,因为毕竟程序员以后可能还会为Add Integer Integer
添加另一个实例,我们需要为该实例做好准备。 (请注意,其他实例甚至可能位于另一个模块中,因此,GHC不能简单地假设不检查所有 all 模块就不会存在该实例,这将是低效率的。)
您需要为6
参数指定类型,否则调用将不明确。
答案 1 :(得分:3)
plus (5 :: Integer) 6
编译器尝试推断6
的类型,但失败。您必须明确指定数字文字的类型,例如:
plus (5 :: Integer) (6 :: Double)
为了编译第二条plus
语句,您不能传递6.0
,因为此值是Float
或Double
,并且您没有为Add
定义的Double Double
的实例。如果需要的话,可以将其类型指定为Integer
:
plus (5.0 :: Double) (6 :: Integer)