В общем, мне интересно, есть ли способ написать обобщенный c сгиб, который обобщает функцию, которая применяет тип forall
, такой как:
f :: forall a. Data (D a) => D a -> b
при некотором типе данных D
для которого instance Data (D a)
(возможно, с ограничениями на a
). Чтобы быть конкретным, рассмотрим что-то даже такое простое, как False `mkQ` isJust
, или, как правило, запрос к конструктору типа данных с более высоким родом. Аналогично, рассмотрим преобразование mkT (const Nothing)
, которое затрагивает только один конкретный тип с более высоким родом.
Без явных сигнатур типов они завершаются ошибкой с No instance for Typeable a0
, что, вероятно, является ограничением мономорфизма в действии. Справедливо. Однако, если мы добавим явные подписи типов:
t :: GenericT
t = mkT (const Nothing :: forall a. Data a => Maybe a -> Maybe a)
q :: GenericQ Bool
q = False `mkQ` (isJust :: forall a. Data a => Maybe a -> Bool)
, вместо этого нам скажут, что тип внешних подписей forall
неоднозначен:
Could not deduce (Typeable a0)
arising from a use of ‘mkT’
from the context: Data a
bound by the type signature for:
t :: GenericT
The type variable ‘a0’ is ambiguous
Я не могу обернуть свою голова вокруг этого. Если я правильно понимаю, что a0
- это переменная в t :: forall a0. Data a0 => a0 -> a0
, как она может быть более двусмысленной, чем, скажем, mkT not
? Во всяком случае, я бы ожидал, что mkT
будет жаловаться, потому что именно он взаимодействует с isJust
. Кроме того, эти функции являются более полиморфными c, чем ветвление на конкретных типах.
Мне любопытно узнать, является ли это ограничением доказательства внутреннего ограничения isJust :: Data a => ...
- я понимаю, что любой тип Экземпляр Data
, населенный Maybe a
, также должен иметь Data a
, чтобы быть действительным по ограничению экземпляра instance Data a => Data (Maybe a)
.