2010-09-30 5 views
6

Я получаю любопытное предупреждение, когда соответствующий шаблон, но только тогда, когда OverloadedStrings включен ...Почему я получаю это предупреждение от GHCi?

$ 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 с OverloadedStrings, в частности, так как я не получите предупреждение за f без OverloadedStrings, а также не получите предупреждение для g или h, которые отличаются от f только в первом шаблоне (что во всех случаях соответствует только одному конкретному значению).

Исходя из предположения, что это не ошибка в GHC, что мне не хватает?

+0

Возможно ли, что '' '' перегружено так, что '[" "]' эквивалентно '[_]'? – Gabe

+0

Нет, это похоже на '[" "]', а не как '[_]'. – dave4420

+0

Вы тестировали это на GHC 7.0? –

ответ

4

Вот несколько проще пример, который показывает ту же проблему в GHC 6.12.3:

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

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

Только g получает предупреждение о перекрытии -XOverloadedStrings. Я думаю, что это должно быть ошибкой.

+0

Да, это довольно отчетливо ошибка.Нечетным является также то, что удаление сигнатуры типа 'g' (в результате чего его тип выводится как' (IsString t, Eq t) => t -> Bool') заставляет предупреждение уходить. –

2

EDIT: В основном вы хотите, чтобы это (после согласования преобразования обратно из (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' 

Вашей строка должна быть вывод формулы для сопоставления с образца для работы с -XOverloadedStrings. Строка все еще только [Char] с -XOverloadedStrings, но строковые литералы - нет.

Другой способ сделать это, не вызывая предупреждение:

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" 

Источник: http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/type-class-extensions.html#overloaded-strings

+0

Я совпадал с шаблоном на обычном 'String', хотя (в моей реальной программе мне нужно перегружать строки в другой части моего кода), поэтому он уже получил' Eq'. Итак, я не понимаю, как это помогает? – dave4420

+1

@Dave Hinton: он пытается сравнить яблоки с апельсинами, но GHC не уверен, что он может безопасно конвертировать апельсины в яблоки перед сравнением (в частности, у него возникают проблемы с «»). В то время как ввод функции имеет тип String, то, что вы сравниваете с (строковые литералы), сначала нужно преобразовать в строки. – vls

Смежные вопросы