なぜGHCIからこの警告を受けているのですか?
-
26-09-2019 - |
質問
パターンマッチングのときに奇妙な警告がありますが、オーバーロード装飾品が有効になっている場合にのみ...
$ 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.
なぜ警告を受けたのかわかりません f
特に警告が表示されないため、過負荷装置で f
オーバーロードエルドストリングなしで、また警告を受け取らないでください g
また h
, 、それは異なります f
最初のパターンでのみ(すべての場合、単一の特定の値のみに一致します)。
これはGHCのバグではないという仮定で、私は何が欠けていますか?
解決
GHC 6.12.3で同じ問題を示すわずかに簡単な例を次に示します。
f :: String -> Bool
f "" = True
f "a" = False
g :: String -> Bool
g "" = True
g "aa" = False
それだけ g
オーバーラップ警告を取得します -XOverloadedStrings
. 。これはバグでなければならないと思います。
他のヒント
編集:基本的にこれが必要です(からの変換を一致させた後、 (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
(リテラル)。その文字通りを考えると、なぜ(おそらくバグ?)を見つけるのは面白いでしょう ""
適切にデフォルトは文字列になります:
Prelude> show ("" :: (Data.String.IsString t) => t)
<interactive>:1:0:
Warning: Defaulting the following constraint(s) to type `String'
文字列は、パターンマッチングが-xoverloadedstringsで動作するためにeqを導き出す必要があります。文字列はまだ-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"}
それを実行します:
$ 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"
所属していません StackOverflow