¿Por qué recibo esta advertencia de GHCI?
-
26-09-2019 - |
Pregunta
Estoy recibiendo una curiosa advertencia cuando coincide con el patrón, pero solo cuando sobrecargó se habilita ...
$ 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.
No entiendo por qué recibo la advertencia para f
con SobrecaredStrings, particularmente porque no recibo la advertencia para f
sin fuerzas sobrecargadas, y tampoco obtiene la advertencia para g
o h
, que difieren de f
solo en el primer patrón (que en todos los casos coincide solo con un solo valor particular).
Suponiendo que esto no es un error en GHC, ¿qué me estoy perdiendo?
Solución
Aquí hay un ejemplo un poco más simple que muestra el mismo problema en GHC 6.12.3:
f :: String -> Bool
f "" = True
f "a" = False
g :: String -> Bool
g "" = True
g "aa" = False
Solamente g
Obtiene la advertencia de superposición con -XOverloadedStrings
. Creo que esto tiene que ser un error.
Otros consejos
Editar: básicamente quieres esto (después de coincidir con la conversión de regreso de (IsString b) => b
dentro [Char]
Pero la coincidencia se realiza en tipos consistentes):
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"
De lo contrario, GHC advierte sobre la coincidencia "" :: String
a "" :: (Data.String.IsString t) => t
(literal). Sería interesante averiguar por qué (¿probablemente un error?) Dado ese literal ""
De manera predeterminada correctamente, la cadena:
Prelude> show ("" :: (Data.String.IsString t) => t)
<interactive>:1:0:
Warning: Defaulting the following constraint(s) to type `String'
Su cadena debe estar derivando EQ para que la coincidencia de patrones funcione con -xoverloadedstrings. La cadena sigue siendo solo [char] con -xoverloadedstrings, pero los literales de cadena no lo son.
Otra forma de hacer esto sin activar una advertencia:
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"}
Ejecutarlo:
$ 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"
Fuente: http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/type-class-extensions.html#verloaded-stings