Я сократил все до самого необходимого, так что терпите меня, если приведенный ниже пример кода является надуманным. Допустим, у нас есть:
class Foo a where
foo :: a
data Type a = Type a
instance (Foo a) => Foo (Type a) where
foo = Type foo
Теперь предположим, что я хочу сделать Type a
экземпляром, скажем, Show
всякий раз, когда a
является экземпляром как Foo
, так и Show
(Show
был выбран, чтобы избежать определения другого класса типов). Итак, как мы хотим, чтобы Type a
был экземпляром Show
? Ну, если мы не сумасшедшие, мы, конечно, хотели бы, чтобы это было что-то вроде
instance (Foo a, Show a) => Show (Type a) where
show (Type x) = show x
или, может быть
instance (Foo a, Show a) => Show (Type a) where
show (Type x) = "Blabla " ++ (show x)
Это все здорово и отлично работает. По какой-то необъяснимой причине мы хотели бы, чтобы show
выводил то, что foo :: a
выглядит / отображается! В нашей надуманной обстановке я не могу представить, зачем нам это нужно, но допустим, что мы хотим. Не должен
instance (Foo a, Show a) => Show (Type a) where
show _ = show foo
Покажи фокус?
Увы, GHC говорит
Переменная неоднозначного типа 'a' в ограничениях: 'Foo a' [...] 'Show a'
Может быть, GHC не может понять, о каком foo
я говорю. Я имею в виду foo :: Type a
или foo :: a
? Изменение предыдущего фрагмента на
instance (Foo a, Show a) => Show (Type a) where
show _ = show (foo :: a)
дает мне
Не удалось вывести (Foo a1) из context (), возникающего из-за использования 'foo' в [...] Возможное исправление: добавить (Foo a1) в контекст сигнатуры типа выражения В первом аргументе 'show' , а именно '(foo :: a)' в выражении: show (foo :: a)
В этот момент я начинаю думать, что неправильно понял кое-что. Тем не менее, у меня есть странное ощущение, что подобные конструкции работали для меня в прошлом.