为什么我从GHCi得到这个警告?

问题描述:

我得到一个奇怪的警告时,模式匹配,但只启用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

这里有一个稍微简单在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

编辑:基本上,你想要这个(匹配来自(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