У меня есть (вполне) законный случай, когда есть две реализации экземпляра типа, и я хочу указать вариант по умолчанию. Заметив, что выполнение модульной арифметики с типами Int
привело к множеству коллизий хешей, я хочу попробовать GHC's Int64. У меня есть следующий код:
class Hashable64 a where
hash64 :: a -> Int64
instance Hashable64 a => Hashable a where
hash = fromInteger . toInteger . hash64
instance Hashable64 a => Hashable64 [a] where
hash64 = foldl1 (\x y -> x + 22636946317 * y) . map hash64
и экземпляр Hashable64 Char
,что, таким образом, приводит к двум реализациям для Hashable String
, а именно:
Data.Hashable
. Hashable64
например, затем преобразование в обычный Int
для экземпляра Data.Hashable
. Второй путь кода может быть лучше, потому что он выполняет хеширование с Int64
с. Могу ли я указать использование этого производного экземпляра Hashable String ?
Извините, я забыл добавить, что уже пробовал использовать перекрывающиеся экземпляры; возможно я просто не правильно реализую? В документации по перекрывающимся экземплярам говорится, что это работает, когда один экземпляр более конкретен. Но когда я пытаюсь добавить конкретный экземпляр для Hashable String
, ситуация не улучшается. Полный код на [ http://pastebin.com/9fP6LUX2 ] (извините за лишний заголовок по умолчанию).
instance Hashable String where
hash x = hash (hash64 x)
Я получаю
Matching instances:
instance (Hashable a) => Hashable [a] -- Defined in Data.Hashable
instance [overlap ok] Hashable String
-- Defined at Hashable64.hs:70:9-23
Любые другие решения этой конкретной проблемы: добро пожаловать. Хорошее решение может дать представление об этой проблеме перекрывающихся экземпляров.