Я работаю с Data.Typeable и, в частности, хочу иметь возможность генерировать правильные типы определенного типа (скажем *
). Проблема, с которой я сталкиваюсь, заключается в том, что TypeRep позволяет нам выполнить следующее (работа с версией в GHC 7.8):
let maybeType = typeRep (Proxy :: Proxy Maybe)
let maybeCon = fst (splitTyConApp maybeType)
let badType = mkTyConApp maybeCon [maybeType]
Здесь badType
является в некотором смысле представлением типа Maybe Maybe, который не является допустимым типом любого вида:
> :k Maybe (Maybe)
<interactive>:1:8:
Expecting one more argument to ‘Maybe’
The first argument of ‘Maybe’ should have kind ‘*’,
but ‘Maybe’ has kind ‘* -> *’
In a type in a GHCi command: Maybe (Maybe)
Я не ищу, чтобы это выполнялось на уровне типа, но я хотел бы написать программу, которая достаточно умна, чтобы избежать создания таких типов во время выполнения. Я могу сделать это с помощью уровней данных на уровне TypeRep
. В идеале у меня было бы что-то вроде
data KindRep = Star | KFun KindRep KindRep
и иметь функцию kindOf
с kindOf Int = Star
(возможно, действительно kindOf (Proxy :: Proxy Int) = Star
) и kindOf Maybe = KFun Star Star
, чтобы я мог "добросердечно проверить" значение TypeRep.
Я думаю, что могу сделать это вручную с помощью поликидного типа, например Typeable
, но я бы предпочел не писать собственные экземпляры для всего. Я также предпочел бы не возвращаться к GHC 7.6 и использовать тот факт, что существуют отдельные классы типов для типов Typeable различных типов. Я открыт для методов, которые получают эту информацию от GHC.