2010-09-30 45 views
6

我得到一個奇怪的警告時,模式匹配,但只啓用OverloadedStrings當...爲什麼我從GHCi得到這個警告?

$ ghci -Wall 
GHCi, version 6.12.1: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Prelude> let f x = case (x :: [String]) of {[""] -> "root"; ["product", _] -> "product"; _ -> "unknown"} 
Prelude> :q 
Leaving GHCi. 
$ ghci -Wall -XOverloadedStrings 
GHCi, version 6.12.1: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Prelude> let f x = case (x :: [String]) of {[""] -> "root"; ["product", _] -> "product"; _ -> "unknown"} 

<interactive>:1:10: 
    Warning: Pattern match(es) are overlapped 
      In a case alternative: [""] -> ... 
Prelude> let g x = case (x :: [String]) of {[] -> "root"; ["product", _] -> "product"; _ -> "unknown"} 
Prelude> let h x = case (x :: [String]) of {["oops"] -> "root"; ["product", _] -> "product"; _ -> "unknown"} 
Prelude> :q 
Leaving GHCi. 

我不明白爲什麼我得到警告爲f與OverloadedStrings,特別是因爲我不在沒有OverloadedStrings的情況下獲得f的警告,也不會收到gh的警告,這些警告僅在第一種模式(在所有情況下僅匹配單個特定值)與f不同。

假設這不是GHC中的錯誤,我錯過了什麼?

+0

有沒有可能重載'''',使得[[「」]'等於'[_]'? – Gabe 2010-09-30 17:58:32

+0

不,它的匹配就好像它是[[「」]',而不是它就是'[_]'。 – dave4420 2010-09-30 18:44:15

+0

你在GHC 7.0上測試過了嗎? – 2010-09-30 18:56:38

回答

4

這裏有一個稍微簡單在GHC 6.12.3中顯示相同問題的示例:

f :: String -> Bool 
f "" = True 
f "a" = False 

g :: String -> Bool 
g "" = True 
g "aa" = False 

只有g得到-XOverloadedStrings的重疊警告。我認爲這必須是一個錯誤。

+0

是的,這很明顯是一個錯誤。奇怪的是,刪除'g'的類型簽名(導致它的類型被推斷爲'(IsString t,Eq t)=> t - > Bool')使得警告消失。 – 2010-10-02 14:38:19

2

編輯:基本上,你想要這個(匹配來自(IsString b) => b轉換回[Char]之後,但匹配是一致的類型進行):

f :: [String] -> String 
f = matchf 

matchf :: (Show b, IsString a, Eq a, IsString b) => [a] -> b 
matchf x = case x of [""] -> "root"; ["product", _] -> "product"; _ -> "unknown" 

否則GHC發出警告匹配"" :: String"" :: (Data.String.IsString t) => t(文字)。這將給予是有趣的,看看爲什麼字面""正確默認字符串(可能是一個錯誤?):

Prelude> show ("" :: (Data.String.IsString t) => t) 

<interactive>:1:0: 
    Warning: Defaulting the following constraint(s) to type `String' 

你的字符串必須是派生的EQ模式匹配-XOverloadedStrings工作。字符串仍然只是[Char]與-XOverloadedStrings,但字符串文字不是。

另一種方式來做到這一點,而不會觸發報警:

test.hs:

import GHC.Exts(IsString(..)) 

newtype OString = OString String deriving (Eq, Show) 
instance IsString OString where fromString = OString 

f :: [OString] -> OString 
f x = case (x :: [OString]) of {[""] -> "root"; ["product", _] -> "product"; _ -> "unknown"} 

運行:

$ ghci -Wall -XOverloadedStrings 
GHCi, version 6.12.1: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Prelude> :l test.hs 
[1 of 1] Compiling Main    (test.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> f [] 
OString "unknown" 
*Main> f [""] 
OString "root" 
*Main> f ["product"] 
OString "unknown" 
*Main> f ["product", "x"] 
OString "product" 

來源:http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/type-class-extensions.html#overloaded-strings

+0

雖然我在普通的'String'上進行了模式匹配(在我的真實程序中,我需要在我的代碼的不同部分中重載字符串),所以它已經導出了'Eq'。所以,我不明白這有何幫助? – dave4420 2010-10-01 08:47:03

+1

@Dave Hinton:它試圖比較蘋果和橘子,但GHC不確定它能否在比較之前安全地將橘子轉換成蘋果(具體來說,它在「」中遇到了問題)。雖然函數輸入是String類型的,但您將它與(字符串文字)進行比較必須首先轉換爲字符串。 – vls 2010-10-01 15:23:54

相關問題