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