Специализированный экземпляр класса в PureScript

Скажем, у меня есть следующий тип:

newtype T1 a = T1 a

Я могу сделать для него Show экземпляр:

instance showT1Generic :: Show a => Show (T1 a) where
  show (T1 a) = "generic: " <> show a

Однако, допустим, я хочу сделать что-то особенное для типов T1 Int. Я пробовал это сделать:

instance showT1Int :: Show (T1 Int) where
  show (T1 a) = "int: " <> show a

и он компилируется, однако запуск в psci работает не так, как ожидалось:

> T1 'a'
generic: 'a'

> T1 1
generic: 1

Я делаю это неправильно?


person levant pied    schedule 03.03.2017    source источник


Ответы (1)


Определение обоих этих экземпляров вызовет OverlappingInstances предупреждение по той причине, которую вы здесь видите - это может сделать выбранный экземпляр непредсказуемым.

Я думаю, что если вы измените порядок определений экземпляров, это сработает, но на самом деле не рекомендуется игнорировать предупреждение OverlappingInstances.

На самом деле вы не можете делать то, что пытаетесь здесь сделать - вы можете изменить поведение экземпляра с помощью нового типа, но специализация экземпляров для некоторых конкретных типов и наличие общего запасного варианта всегда будет приводить к перекрывающимся экземплярам в его нынешнем виде. . Возможно, если мы введем цепочки экземпляров, это станет возможным, но до тех пор вы лучше отключить использование мономорфных функций для такого рода вещей.

person gb.    schedule 03.03.2017
comment
Это также не соответствует общему коду: f :: forall a. (Show a) => T1 a -> String; f = show никогда не выберет Show (T1 Int). Параметричность запрещает использование специальной оболочки. - person rightfold; 04.03.2017
comment
Спасибо, gb., Думаю, я не видел предупреждения, потому что использовал исключительно psci. - person levant pied; 06.03.2017