Использование стандартных библиотек дженериков Haskell для типизированных типов -изоморфизмов

Только на платформе Haskell существует несколько универсальных библиотек с многочисленными перекрывающимися модулями (syb., Data.Typeable, Data.Data,GHC.Generics), но у меня возникли проблемы с очень простой общей задачей программирования.

Я хочу иметь возможность конвертировать между типами одной и той же формы, т.е. мне нужна полиморфная, типизированная функция преобразования между изоморфными типами, по сути то, что предлагается в конце этой статьи(PDF ), где упоминаются семейства индексированных типов.

Меня не интересует отказ от моего шаблона, а скорее возможность создавать новые библиотеки на основе абстракций суммы и произведения.

Вопрос ниже относится к GHC.Generic, который, по моему мнению, был ближе всего к тому, что мне нужно, но приветствуются и другие решения.


Следующие два типа имеют одинаковую форму

data Pair = Pair Char Int deriving (Generic, Show)
data Pair2 = Pair2 Char Int deriving (Generic, Show)

Я хочу преобразовать значения между ними, используя GHC.Generics. Следующее не проходит проверку типов из-за всех фантомных параметров и прочей чепухи:

f :: Pair -> Pair2
f = to. from

В конечном итоге мне нужна функция, похожая на fromInteger, которая имеет полиморфное возвращаемое значение для любогоGeneric(или любой другой класс, который может поддерживать этот экземпляр ). Думаю, я ищу что-то вродеGHC.Generics:

--class:
type family NormalForm a
class ToGeneric a where
    to :: a -> NormalForm a
class FromGeneric b where
    from :: NormalForm b -> b

--examples:
data A = A Char Int deriving Show
data B = B Char Int deriving Show

type instance NormalForm A = (Char,Int)
instance ToGeneric A where
    to (A a b) = (a,b)
instance FromGeneric A where
    from (a,b) = A a b

type instance NormalForm B = (Char,Int)
instance ToGeneric B where
    to (B a b) = (a,b)
instance FromGeneric B where
    from (a,b) = B a b

-- the function I'm looking for
coerce :: (ToGeneric a, FromGeneric b, NormalForm a ~ NormalForm b)=> a -> b
coerce = from. to

С вышеперечисленным мы можем делать все, что захочу:

*Main> (coerce $A 'a' 1) :: B
B 'a' 1
*Main> (coerce $A 'a' 1) :: A
A 'a' 1

РЕДАКТИРОВАТЬ:Вот как на самом деле работает функция Натана Хауэлла f.

Вопросы

  1. Возможно ли это сделать с библиотеками, которые в настоящее время находятся на платформе haskell?

  2. Если нет, можно ли определить библиотеку, которая использует существующий механизм derivingдля Generic, Dataи т. д., не прибегая к TH?

17
задан jberryman 24 November 2012 в 16:23
поделиться