Haskell - получить TypeRep из экземпляра конкретного типа
Я хочу написать функцию с такой сигнатурой типа:
getTypeRep :: Typeable a => t a -> TypeRep
где TypeRep будет представлением типа для a, а не для t a. То есть, компилятор должен автоматически возвращать правильное представление типа на любых сайтах вызова [to getTypeRep], которые будут иметь конкретные типы для.
Чтобы добавить некоторый контекст, я хочу создать тип данных типа "Динамический тип", с твистом, что он будет помнить тип верхнего уровня, но не его параметр. Например, я хочу превратить MyClass a в Dynamic MyClass, и вышеуказанная функция будет использоваться для создания экземпляров Dynamic MyClass, которые хранят представление параметра типа a.
Ответы
Ответ 1
Ну, а как насчет использования переменных типа для выбора внутреннего компонента:
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Dynamic
import Data.Typeable
getTypeRep :: forall t a . Typeable a => t a -> TypeRep
getTypeRep _ = typeOf (undefined :: a)
Работает для меня:
*Main> getTypeRep (Just ())
()
*Main> getTypeRep (Just 7)
Integer
*Main> getTypeRep ([True])
Bool
Интересный дизайн.
Ответ 2
В решении касательной к дону обратите внимание, что для кода редко требуется ScopedTypeVariables. Это просто делает решение более чистым (но менее портативным). Решение без типов областей:
{-# LANGUAGE ExplicitForAll #-}
import Data.Typeable
helper :: t a -> a
helper _ = undefined
getTypeRep :: forall t a. Typeable a => t a -> TypeRep
getTypeRep = typeOf . helper
Ответ 3
Эта функция (сейчас) существует в Data.Typeable
typeRep