Использование стандартных универсальных библиотек 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
EDIT: Вот как Натан Хауэллf
функция, кажется, работает ниже, на самом деле.
Is this possible to do with libraries currently in the haskell platform?
If not, could a library be defined that leveraged the existing deriving
mechanism for Generic
, Data
, etc. without resorting to TH?