Why am I getting this warning from GHCi?
Asked Answered
S

2

8

I'm getting a curious warning when pattern matching, but only when OverloadedStrings is enabled...

$ 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.

I don't understand why I get the warning for f with OverloadedStrings, particularly since I don't get the warning for f without OverloadedStrings, and also don't get the warning for g or h, which differ from f only in the first pattern (which in all cases matches only a single particular value).

On the assumption that this is not a bug in GHC, what am I missing?

Smelter answered 30/9, 2010 at 17:49 Comment(5)
Is it possible that "" is overloaded such that [""] is equivalent to [_]?Chemosmosis
No, it's matching as if it was [""], not as if it was [_].Smelter
Have you tested this on GHC 7.0?Townsfolk
I wasn't aware there was a GHC 7.0! The GHC homepage lists 6.12.3 as the latest version. Where would I download it from?Smelter
7.0 is in RC stage right now. If you aren't deep into Haskell/GHC then perhaps you should wait for the official release, I was just curious if you had tried seeing as the type checker was overhauled.Townsfolk
S
5

Here's a slightly simpler example that shows the same issue in GHC 6.12.3:

f :: String -> Bool
f "" = True
f "a" = False

g :: String -> Bool
g "" = True
g "aa" = False

Only g gets the overlap warning with -XOverloadedStrings. I think this has to be a bug.

Sabellian answered 30/9, 2010 at 21:47 Comment(1)
Yes, this is quite clearly a bug. What's also odd is that removing the type signature of g (causing its type to be inferred as (IsString t, Eq t) => t -> Bool) makes the warning go away.Kistner
V
2

EDIT: Basically you want this (after matching converting back from (IsString b) => b into [Char] but matching is done in consistent types):

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"

Otherwise GHC warns about matching "" :: String to "" :: (Data.String.IsString t) => t (literal). It would be interesting to find out why (probably a bug?) given that literal "" properly defaults to String:

Prelude> show ("" :: (Data.String.IsString t) => t)

<interactive>:1:0:
    Warning: Defaulting the following constraint(s) to type `String'

Your string must be deriving Eq for pattern matching to work with -XOverloadedStrings. String is still just [Char] with -XOverloadedStrings but string literals are not.

Another way to do this without triggering a warning:

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"}

Run it:

$ 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"

Source: http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/type-class-extensions.html#overloaded-strings

Villiers answered 30/9, 2010 at 17:49 Comment(2)
I am pattern matching on ordinary String s though (in my real program, I need overloaded strings in a different part of my code), so it has already derived Eq. So, I don't see how this helps?Smelter
@Dave Hinton: it's trying to compare apples to oranges but GHC is unsure that it can convert oranges into apples safely prior to the comparison (specifically, it is having trouble with ""). While the function input is of type String, what you're comparing it to (string literals) have to be converted into Strings first.Villiers

© 2022 - 2024 — McMap. All rights reserved.