Perché ricevo questo avvertimento da GHCI?
-
26-09-2019 - |
Domanda
Sto ricevendo un curioso avvertimento durante la corrispondenza del modello, ma solo quando è abilitato i corde a sovraccarico ...
$ 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.
Non capisco perché ricevo l'avvertimento f
con corde sovraccarichi, soprattutto perché non ricevo l'avvertimento per f
senza cornici di sovraccarico e non ricevere anche l'avvertimento g
o h
, che differiscono da f
solo nel primo modello (che in tutti i casi corrisponde a un solo valore particolare).
Sul presupposto che questo non è un bug in GHC, cosa mi manca?
Soluzione
Ecco un esempio leggermente più semplice che mostra lo stesso problema in GHC 6.12.3:
f :: String -> Bool
f "" = True
f "a" = False
g :: String -> Bool
g "" = True
g "aa" = False
Solo g
Ottiene l'avvertimento di sovrapposizione con -XOverloadedStrings
. Penso che questo debba essere un bug.
Altri suggerimenti
Modifica: fondamentalmente lo vuoi (dopo aver abbinato la conversione da (IsString b) => b
in [Char]
Ma la corrispondenza viene eseguita in tipi coerenti):
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"
Altrimenti GHC avverte della corrispondenza "" :: String
a "" :: (Data.String.IsString t) => t
(letterale). Sarebbe interessante scoprire perché (probabilmente un bug?) Dato quel letterale ""
correttamente predefinito per la stringa:
Prelude> show ("" :: (Data.String.IsString t) => t)
<interactive>:1:0:
Warning: Defaulting the following constraint(s) to type `String'
La tua stringa deve derivare EQ per la corrispondenza dei pattern per funzionare con -Overloadstrings. La stringa è ancora solo [char] con -overloadstrings ma le letterali string non lo sono.
Un altro modo per farlo senza innescare un avvertimento:
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"}
Eseguirlo:
$ 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"
Fonte: http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/type-class-extensions.html#overload-strings