2017-01-20 27 views
2

我有一個文件OptionList.hs,其中有一個名爲OptionList的新數據類型。我想隱藏EmptyOpt當OptionList被顯示:模式重疊,爲什麼發生?

module OptionList (
    OptionList, 
    voidOption, 
    (+:) 
) where 


data OptionList a b = EmptyOpt | OptionList { optListHead :: a, optListTail :: b } deriving (Read) 

instance (Show a, Show b) => Show (OptionList a b) where 
    show (OptionList voidOption a) = "{" ++ (show a) ++"}" 
    show (OptionList a voidOption) = "{" ++ (show a) ++"}" 
    show (OptionList a b) = "{"++ (show a) ++ ", " ++ (show b) ++"}" 
    show voidOption = "" 




voidOption::(OptionList Int Int) 
voidOption = EmptyOpt 



(+:) :: a -> b -> (OptionList a b) 
infixr 5 +: 
t1 +: t2 = OptionList t1 t2 

然後,我有主文件todo.hs

import OptionList 


main = do 
    print (0 +: "test" +: voidOption) 

但是,編譯器告訴該模式在OptionList.hs匹配重疊:

OptionList.hs:12:9: Warning: 
    Pattern match(es) are overlapped 
    In an equation for ‘show’: 
     show (OptionList a voidOption) = ... 
     show (OptionList a b) = ... 

而當我執行它時,它確實是重疊的。它產生的輸出如下:

{{}} 

(我想這是{0, {"test"}}

但爲什麼這些圖案重疊?

回答

8

在線路

show (OptionList voidOption a) = "{" ++ (show a) ++"}" 

voidOption是一個新鮮的局部變量,像a是。它與下面定義的voidOption變量沒有關係。從本質上講,上面的行相當於

show (OptionList b a) = "{" ++ (show a) ++"}" 

因此,它總是匹配和重疊以下行。

如果我們將模式中的所有變量視爲由模式定義的變量,則很容易記住這一點。從某種意義上說,他們的價值觀是「走出去」的模式,而不是「進入」。

打開警告(-Wall)會警告您這個錯誤,因爲voidOption的新本地綁定會影響全局。

在模式中,您應該使用EmptyOpt構造函數代替。例如。

show (OptionList EmptyOpt a) = "{" ++ (show a) ++"}" 
+0

謝謝!我按照建議更新了代碼,但出現了更多錯誤。查看我的編輯 –

+0

@BrunoCorrêaZimmermann作爲一個新問題,「更新」會更好,因爲它是關於新代碼的一個新問題。但是一個小提示:在你的'show'實現中,你有兩個任意類型'a'和'b',你知道的只是它們可以是'show'n。你爲什麼認爲你可以將它們與'OptionList'類型的構造函數進行模式匹配? – amalloy

+2

好的!抱歉。我會提出一個新問題 –