首先,我的背景是用C ++编写的,所以尽量不要太用力地击打我。
在这个人为的例子中,我试图定义一个如下所示的多态类型:
data T x y
= Cons1 x
| Cons2 y
| Neither
deriving (Show)
我想要一个数据类型,其中包含x
类型的值,类型y
或两者都没有。各种Maybe a
的变体。当我尝试这样做时:
main = do
let v = Cons1 1
putStrLn (show v)
出现了一些含糊之处:
No instance for (Show y0) arising from a use of `show'
The type variable `y0' is ambiguous
Note: there are several potential instances:
instance (Show x, Show y) => Show (T x y)
-- Defined at C:\Projects\Private\Haskell\Play\play.hs:14:27
instance Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
...plus 25 others
In the first argument of `putStrLn', namely `(show t)'
In a stmt of a 'do' block: putStrLn (show t)
In the expression:
do { let t = Cons1 1;
putStrLn (show t) }
这是为什么?为什么会有歧义? 1
中的Cons1 1
来自我所理解的数字,这些数字都来自Show。我认为,构造函数本身就是一个鉴别器,正在制作Cons1 1 /= Cons2 1
。
答案 0 :(得分:4)
使用Cons1 1
,编译器只能在x
中派生data T x y
类型,无法推断y
。 x
变为Num a
,但是y
呢?在这种情况下,您需要手动指定它:
main = do
let v = (Cons1 1 :: T Int Int) -- just an example
putStrLn (show v)
在某些情况下,如果您使用显式函数类型,编译器将能够自动推断它。但在这种情况下,它确实没有任何提示。
与Nothing
对其自身含糊不清的情况相同。是Maybe String
,Maybe Int
,Maybe Double
,......?