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?

¿Fue útil?

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top