1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
|
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE PolyKinds #-}
{-# OPTIONS_GHC -fno-warn-deprecations #-}
module Main (main, toTreeC, toDataFamC) where
import qualified GHC.Generics as GHC
import Generics.SOP
import Generics.SOP.TH
import qualified Generics.SOP.Type.Metadata as T
import HTransExample
-- Generic show, kind of
gshow :: (Generic a, All2 Show (Code a)) => a -> String
gshow x = gshowS (from x)
gshowS :: (All2 Show xss) => SOP I xss -> String
gshowS (SOP (Z xs)) = gshowP xs
gshowS (SOP (S xss)) = gshowS (SOP xss)
gshowP :: (All Show xs) => NP I xs -> String
gshowP Nil = ""
gshowP (I x :* xs) = show x ++ (gshowP xs)
-- Generic enum, kind of
class Enumerable a where
enum :: [a]
genum :: (Generic a, All2 Enumerable (Code a)) => [a]
genum =
fmap to genumS
genumS :: (All SListI xss, All2 Enumerable xss) => [SOP I xss]
genumS =
concat (fmap apInjs_POP
(hsequence (hcpure (Proxy :: Proxy Enumerable) enum)))
-- GHC.Generics
data Tree = Leaf Int | Node Tree Tree
deriving (GHC.Generic)
tree :: Tree
tree = Node (Leaf 1) (Leaf 2)
abc :: ABC
abc = B
instance Generic Tree
instance HasDatatypeInfo Tree
data ABC = A | B | C
deriving (GHC.Generic)
instance Generic ABC
instance HasDatatypeInfo ABC
data Void
deriving (GHC.Generic)
instance Generic Void
instance HasDatatypeInfo Void
data family DataFam a b c
data instance DataFam Int (Maybe b) c = DF b c
deriving (GHC.Generic)
dataFam :: DataFam Int (Maybe Int) Int
dataFam = DF 1 2
instance Generic (DataFam Int (Maybe b) c)
instance HasDatatypeInfo (DataFam Int (Maybe b) c)
instance Show Tree where
show = gshow
instance Show ABC where
show = gshow
instance Show Void where
show = gshow
instance (Show b, Show c) => Show (DataFam Int (Maybe b) c) where
show = gshow
instance Enumerable ABC where
enum = genum
instance Enumerable Void where
enum = genum
-- Template Haskell
data TreeB = LeafB Int | NodeB TreeB TreeB
treeB :: TreeB
treeB = NodeB (LeafB 1) (LeafB 2)
deriveGeneric ''TreeB
data ABCB = AB | BB | CB
abcB :: ABCB
abcB = BB
deriveGeneric ''ABCB
data VoidB
deriveGeneric ''VoidB
data family DataFamB a b c
data instance DataFamB Int (Maybe b) c = DFB b c
dataFamB :: DataFamB Int (Maybe Int) Int
dataFamB = DFB 1 2
deriveGeneric 'DFB
instance Show TreeB where
show = gshow
instance Show ABCB where
show = gshow
instance Show VoidB where
show = gshow
instance (Show b, Show c) => Show (DataFamB Int (Maybe b) c) where
show = gshow
instance Enumerable ABCB where
enum = genum
instance Enumerable VoidB where
enum = genum
-- Orphan approach
data TreeC = LeafC Int | NodeC TreeC TreeC
treeC :: TreeC
treeC = NodeC (LeafC 1) (LeafC 2)
data ABCC = AC | BC | CC
abcC :: ABCC
abcC = BC
data VoidC
data family DataFamC a b c
data instance DataFamC Int (Maybe b) c = DFC b c
dataFamC :: DataFamC Int (Maybe Int) Int
dataFamC = DFC 1 2
deriveGenericFunctions ''TreeC "TreeCCode" "fromTreeC" "toTreeC"
deriveMetadataValue ''TreeC "TreeCCode" "treeDatatypeInfo"
deriveMetadataType ''TreeC "TreeDatatypeInfo"
deriveGenericFunctions ''ABCC "ABCCCode" "fromABCC" "toABCC"
deriveMetadataValue ''ABCC "ABCCCode" "abcDatatypeInfo"
deriveMetadataType ''ABCC "ABCDatatypeInfo"
deriveGenericFunctions ''VoidC "VoidCCode" "fromVoidC" "toVoidC"
deriveMetadataValue ''VoidC "VoidCCode" "voidDatatypeInfo"
deriveMetadataType ''VoidC "VoidDatatypeInfo"
deriveGenericFunctions 'DFC "DataFamCCode" "fromDataFamC" "toDataFamC"
deriveMetadataValue 'DFC "DataFamCCode" "dataFamDatatypeInfo"
deriveMetadataType 'DFC "DataFamDatatypeInfo"
demotedTreeDatatypeInfo :: DatatypeInfo TreeCCode
demotedTreeDatatypeInfo = T.demoteDatatypeInfo (Proxy :: Proxy TreeDatatypeInfo)
demotedABCDatatypeInfo :: DatatypeInfo ABCCCode
demotedABCDatatypeInfo = T.demoteDatatypeInfo (Proxy :: Proxy ABCDatatypeInfo)
demotedVoidDatatypeInfo :: DatatypeInfo VoidCCode
demotedVoidDatatypeInfo = T.demoteDatatypeInfo (Proxy :: Proxy VoidDatatypeInfo)
demotedDataFamDatatypeInfo :: DatatypeInfo (DataFamCCode b c)
demotedDataFamDatatypeInfo = T.demoteDatatypeInfo (Proxy :: Proxy DataFamDatatypeInfo)
instance Show TreeC where
show x = gshowS (fromTreeC x)
instance Show ABCC where
show x = gshowS (fromABCC x)
instance Show VoidC where
show x = gshowS (fromVoidC x)
instance (Show b, Show c) => Show (DataFamC Int (Maybe b) c) where
show x = gshowS (fromDataFamC x)
instance Enumerable ABCC where
enum = fmap toABCC genumS
instance Enumerable VoidC where
enum = fmap toVoidC genumS
-- Tests
main :: IO ()
main = do
print tree
print abc
print dataFam
print $ (enum :: [ABC])
print $ (enum :: [Void])
print $ datatypeInfo (Proxy :: Proxy Tree)
print $ datatypeInfo (Proxy :: Proxy Void)
print $ datatypeInfo (Proxy :: Proxy (DataFam Int (Maybe Int) Int))
print treeB
print abcB
print dataFamB
print $ (enum :: [ABCB])
print $ (enum :: [VoidB])
print $ datatypeInfo (Proxy :: Proxy TreeB)
print $ datatypeInfo (Proxy :: Proxy VoidB)
print $ datatypeInfo (Proxy :: Proxy (DataFamB Int (Maybe Int) Int))
print treeC
print abcC
print dataFamC
print $ (enum :: [ABCC])
print $ (enum :: [VoidC])
print treeDatatypeInfo
print demotedTreeDatatypeInfo
print demotedDataFamDatatypeInfo
print (treeDatatypeInfo == demotedTreeDatatypeInfo)
print (abcDatatypeInfo == demotedABCDatatypeInfo)
print (voidDatatypeInfo == demotedVoidDatatypeInfo)
print (dataFamDatatypeInfo == demotedDataFamDatatypeInfo)
print $ convertFull tree
|