2014-12-03 74 views
3

首先,我的背景是C++,所以儘量不要讓我失望過度。Haskell - 多態類型的演繹秀

在這個人爲的例子,我試圖定義一個多態類型,看起來像這樣:

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) } 

這是爲什麼?爲什麼有歧義? 1Cons1 1是我所瞭解的一個數字,它全部來源於Show。我想,構造函數本身充當鑑別器,製作Cons1 1 /= Cons2 1

回答

4

隨着Cons1 1編譯器只能夠推導data T x yx類型,也沒有辦法來推斷yx變成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,...?

+0

如果我註釋掉打印行,編譯器會接受它。編譯器如此懶惰,直到我調用show時纔會生成show函數?另外,你將如何模擬這種類型?我感覺我的例子是糟糕的形式! – 2014-12-03 21:46:06

+0

@JörgenSigvardsson奇怪。它應該生成一個「do'塊中的最後一個語句必須是表達式」編譯錯誤「。你的類型不是一個糟糕的形式。 '或者'的建模方式幾乎是相同的(每種類型有兩種類型和兩種類型的構造函數)。 – Shoe 2014-12-03 22:13:25

+0

我用空字符串替換了打印的表達式,而不是刪除。對此感到困惑不已。 – 2014-12-03 22:16:21