为什么我会收到来自 GHCi 的警告?

发布于 2024-09-25 18:20:17 字数 1421 浏览 1 评论 0原文

我在模式匹配时收到一个奇怪的警告,但仅在启用 OverloadedStrings 时...

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

我不明白为什么我会收到带有 OverloadedStrings 的 f 警告,特别是因为我没有得到没有 OverloadedStrings 的 f 会收到警告,并且也不会收到与 f 不同的 gh 的警告> 仅在第一个模式中(在所有情况下仅匹配单个特定值)。

假设这不是 GHC 中的错误,我错过了什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薯片软お妹 2024-10-02 18:20:17

下面是一个稍微简单的示例,显示了 GHC 6.12.3 中的相同问题:

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

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

只有 g 会通过 -XOverloadedStrings 获得重叠警告。我认为这一定是一个错误。

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.

追风人 2024-10-02 18:20:17

编辑:基本上你想要这个(在从 (IsString b) => b 匹配转换回 [Char] 之后,但匹配是以一致的类型完成的):

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"

否则 GHC 会发出警告关于将 "" :: String"" :: (Data.String.IsString t) => 匹配t(字面意思)。找出原因(可能是一个错误?)会很有趣,因为文字 "" 正确地默认为 String:

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

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

您的字符串必须派生 Eq 才能与 -XOverloadedStrings 一起使用模式匹配。字符串仍然只是带有 -XOverloadedStrings 的 [Char],但字符串文字不是。

另一种不触发警告的方法:

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文