Pourquoi ai-je cet avertissement de GHCI?
-
26-09-2019 - |
Question
Je reçois un curieux avertissement lors de la correspondance des modèles, mais seulement lorsque les titulaires de surcharge sont activés ...
$ 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.
Je ne comprends pas pourquoi j'obtiens l'avertissement pour f
avec des monts surchargés, d'autant plus que je n'obtiens pas l'avertissement pour f
sans titulaires de surcharge, et n'obtenez pas non plus l'avertissement pour g
ou h
, qui diffèrent de f
uniquement dans le premier modèle (qui dans tous les cas ne correspond qu'une seule valeur particulière).
En supposant que ce n'est pas un bug en GHC, qu'est-ce que je manque?
La solution
Voici un exemple légèrement plus simple qui montre le même problème dans GHC 6.12.3:
f :: String -> Bool
f "" = True
f "a" = False
g :: String -> Bool
g "" = True
g "aa" = False
Seulement g
Obtient l'avertissement de chevauchement avec -XOverloadedStrings
. Je pense que cela doit être un bug.
Autres conseils
Edit: Fondamentalement, vous voulez cela (après avoir fait correspondre la conversion (IsString b) => b
dans [Char]
mais la correspondance se fait en types cohérents):
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"
Sinon GHC met en garde contre le match "" :: String
à "" :: (Data.String.IsString t) => t
(littéral). Il serait intéressant de découvrir pourquoi (probablement un bug?) Compte tenu de ce littéral ""
La chaîne par défaut est correctement:
Prelude> show ("" :: (Data.String.IsString t) => t)
<interactive>:1:0:
Warning: Defaulting the following constraint(s) to type `String'
Votre chaîne doit dériver EQ pour la correspondance de motifs pour travailler avec -xoverloadStrings. La chaîne est toujours simplement [char] avec -xoverloadStrings mais les littéraux de chaîne ne le sont pas.
Une autre façon de le faire sans déclencher un avertissement:
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"}
Exécuter:
$ 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"