Похоже, вы хотите перекрывающихся экземпляров , поскольку вы хотите иметь instance Out String
, который отличается от instance Show a => Out a
, который перекрывает его.
{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
{-# LANGUAGE OverlappingInstances, UndecidableInstances #-}
class Out a where out :: a -> String
instance Out String where out = id
instance (Show a) => Out a where out = show
Общая рекомендация - избегать использования перекрывающихся экземпляров и неразрешимых экземпляров, если только действительно не требуется, поскольку внесенные ими изменения в проверку типов не переносимы и могут вызвать другие проблемы.
Редактировать
В отношении реализации подумайте о словаре для каждого экземпляра класса. <<
будет предоставлен словарь для экземпляра Out
, который предполагается использовать в качестве скрытого параметра. Поскольку оттуда ищется out
, для вашего RULE
нет места для стрельбы. Если бы out
не было в классе типов и вызывалось из неполиморфной функции, то я ожидал бы, что RULE
будет совпадать, но как это не удивительно, что он не работает.
RULE
/ SPECIALIZE
предназначены только для оптимизации, и ваш код не должен изменять поведение, если оно срабатывает или не срабатывает.
Мне потребовалось некоторое время, чтобы понять, что ты делал, и ад; Вы понимаете, что Haskell - это не C ++, верно? Способы использования полиморфизма весьма различны.