Created
December 20, 2016 02:02
-
-
Save RyanGlScott/f036622053a6874d7a06b353dc366da6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE DefaultSignatures #-} | |
{-# LANGUAGE DeriveGeneric #-} | |
{-# LANGUAGE FlexibleContexts #-} | |
{-# LANGUAGE FlexibleInstances #-} | |
{-# LANGUAGE MultiParamTypeClasses #-} | |
{-# LANGUAGE TypeOperators #-} | |
module GenericIso where | |
import Data.Coerce | |
import GHC.Generics | |
class Convertible a b where | |
convert :: a -> b | |
default convert :: (Generic a, Generic b, GConvertible (Rep a) (Rep b)) | |
=> a -> b | |
convert = to . gconvert . from | |
instance Convertible a a where | |
convert = id | |
class GConvertible f g where | |
gconvert :: f a -> g a | |
instance GConvertible V1 V1 where | |
gconvert = id | |
instance GConvertible U1 U1 where | |
gconvert = id | |
instance Convertible c d => GConvertible (K1 i c) (K1 j d) where | |
gconvert = K1 . convert . unK1 | |
instance GConvertible f g => GConvertible (M1 i c f) (M1 j d g) where | |
gconvert = M1 . gconvert . unM1 | |
instance (GConvertible f1 f2, GConvertible g1 g2) | |
=> GConvertible (f1 :+: g1) (f2 :+: g2) where | |
gconvert (L1 l) = L1 (gconvert l) | |
gconvert (R1 r) = R1 (gconvert r) | |
instance (GConvertible f1 f2, GConvertible g1 g2) | |
=> GConvertible (f1 :*: g1) (f2 :*: g2) where | |
gconvert (l :*: r) = gconvert l :*: gconvert r | |
-------------- | |
-- Examples -- | |
-------------- | |
data A = A String Int deriving Generic | |
data B = B String Int deriving Generic | |
instance Convertible A B | |
instance Convertible B A | |
aToB :: A -> B | |
aToB = convert | |
bToA :: B -> A | |
bToA = convert | |
data List1 a = Nil1 | Cons1 a (List1 a) deriving Generic | |
data List2 a = Nil2 | Cons2 a (List2 a) deriving Generic | |
instance Convertible a b => Convertible (List1 a) (List2 b) | |
instance Convertible a b => Convertible (List2 a) (List1 b) | |
list1ToList2 :: List1 A -> List2 B | |
list1ToList2 = convert | |
list2ToList1 :: List2 A -> List1 B | |
list2ToList1 = convert |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I personally think this is a bad idea for the following reasons:
In my opinion you're much better of to use ordinary functions and pattern matching.