Так Data.Map имеет dataCast2
, что имеет смысл, поскольку имеет конструктор типа arity 2. dataCast1
по умолчанию - const Nothing
. dataCast2
легко определяется как gcast2
.Data.Data - создание dataCast1 для конструктора типа arity 2 (частично специализированного)
Для справки:
class Typeable a => Data a where
dataCast1 :: Typeable1 t => (forall d. Data d => c (t d)) -> Maybe (c a)
dataCast2 :: Typeable2 t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a)
...
gcast1 :: (Typeable1 t, Typeable1 t') => c (t a) -> Maybe (c (t' a))
gcast2 :: (Typeable2 t, Typeable2 t') => c (t a b) -> Maybe (c (t' a b))
Вопрос под рукой заключается в следующем: дано все в Data.Data
, Data.Typeable
и т.д., и дали конструктор типа арностью 2, для которого определяется dataCast2
(скажем, Map
или (,)
), можно ли написать версию dataCast1
, которая делает правильную вещь для частичной специализации этого типа конструктора либо для одного конкретного конструктора за раз, либо вообще?
Интуитивно я считаю, что должно быть хорошее решение, но мои первые несколько попыток разбились и сожжены.
Это похоже на интересную проблему, но я думаю, мне понадобится немного больше фона. Во-первых, вопрос. Что именно вы подразумеваете под «делает правильную вещь для частичного применения конструктора этого типа»? Конструкторы типов могут отображаться частично в заголовке объявления класса или экземпляра, однако в любом другом месте они должны быть полностью применены AFAIK. – 2010-12-01 01:21:16
@Sean Хорошая точка. Я изменил его, чтобы прочитать «частичную специализацию». Дело в том, что вы можете вызвать `myDataCast1` с результатом` Maybe (c (Int, a)) `так же, как можно вызвать` dataCast1` с результатом `Maybe (c (Maybe a))`. – sclv 2010-12-01 02:04:57