Warum bekomme ich diese Warnung von GHCI?
-
26-09-2019 - |
Frage
Ich bekomme eine merkwürdige Warnung, wenn das Musterübereinstimmung angepasst wird, aber nur wenn überladene Strings aktiviert sind ...
$ 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.
Ich verstehe nicht, warum ich die Warnung dafür bekomme f
mit überladenen Strings, zumal ich nicht die Warnung dafür bekomme f
ohne überlastete Strings und auch nicht die Warnung dafür bekommen g
oder h
, was unterscheidet sich von f
Nur im ersten Muster (was in allen Fällen nur mit einem einzigen bestimmten Wert übereinstimmt).
Was fehlt mir, unter der Annahme, dass dies kein Fehler in GHC ist?
Lösung
Hier ist ein etwas einfacheres Beispiel, das das gleiche Problem in GHC 6.12.3 zeigt:
f :: String -> Bool
f "" = True
f "a" = False
g :: String -> Bool
g "" = True
g "aa" = False
Nur g
bekommt die Überlappungswarnung mit -XOverloadedStrings
. Ich denke, das muss ein Fehler sein.
Andere Tipps
Bearbeiten: Im Grunde möchten Sie dies (nachdem Sie die Konvertierung von der Konvertierung von (IsString b) => b
hinein [Char]
Die Übereinstimmung erfolgt jedoch in konsistenten Typen):
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"
Andernfalls warnt GHC vor Matching "" :: String
zu "" :: (Data.String.IsString t) => t
(wörtlich). Es wäre interessant herauszufinden, warum (wahrscheinlich ein Fehler?) Angesichts dieser wörtlichen ""
ordnungsgemäß standardmäßig zu String:
Prelude> show ("" :: (Data.String.IsString t) => t)
<interactive>:1:0:
Warning: Defaulting the following constraint(s) to type `String'
Ihre Zeichenfolge muss EQ für das Musteranpassung für die Arbeit mit -xoverloadedStrings abgeben. String ist immer noch nur [char] mit -xoverloadedstrings, aber String -Literale nicht.
Eine andere Möglichkeit, dies zu tun, ohne eine Warnung auszulösen:
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"}
Starte es:
$ 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"