代码之家  ›  专栏  ›  技术社区  ›  dave4420

为什么我要从GHCI那里得到这个警告?

  •  6
  • dave4420  · 技术社区  · 14 年前

    当模式匹配时,我会收到一个奇怪的警告,但只有当启用重载字符串时…

    $ 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 使用重载字符串,尤其是因为我没有收到 F 如果没有重载字符串,也不会收到 g h 不同于 F 仅在第一个模式中(在所有情况下,仅匹配单个特定值)。

    假设这不是GHC中的错误,我遗漏了什么?

    2 回复  |  直到 14 年前
        1
  •  4
  •   Travis Brown    14 年前

    下面是一个稍微简单一点的例子,它在GHC 6.12.3中显示了相同的问题:

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

    只有 g 获取重叠警告 -XOverloadedStrings . 我想这一定是个虫子。

        2
  •  2
  •   vls    14 年前

    编辑:基本上你想要这个(匹配后转换回 (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进行模式匹配。字符串仍然是带有-XoverloadedStrings的[char],但字符串文本不是。

    另一种不触发警告的方法是:

    试验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