{-# LANGUAGE TypeApplications #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE PatternSynonyms #-} {-# OPTIONS_GHC -Wno-missing-pattern-synonym-signatures #-} {-# OPTIONS_GHC -Wno-incomplete-patterns #-} {-# OPTIONS_GHC -Wno-orphans #-} -- |This module is analogous to 'Generics.MRSOP.Examples.RoseTreeTH', -- but we use no Template Haskell here. module Generics.MRSOP.Examples.RoseTree where import Data.Function (on) import Generics.MRSOP.Base import Generics.MRSOP.Opaque -- * Standard Rose-Tree datatype data R a = a :>: [R a] | Leaf a deriving Show value1, value2, value3 :: R Int value1 = 1 :>: [2 :>: [], 3 :>: []] value2 = 1 :>: [2 :>: [] , Leaf 12] value3 = 3 :>: [Leaf 23 , value1 , value2] -- ** Family Structure type ListCode = '[ '[] , '[ 'I ('S 'Z) , 'I 'Z] ] type RTCode = '[ '[ 'K 'KInt , 'I 'Z] , '[ 'K 'KInt] ] type CodesRose = '[ListCode , RTCode] type FamRose = '[ [R Int] , R Int] -- ** Instance Decl instance Family Singl FamRose CodesRose where sfrom' (SS SZ) (El (a :>: as)) = Rep $ Here (NA_K (SInt a) :* NA_I (El as) :* NP0) sfrom' (SS SZ) (El (Leaf a)) = Rep $ There (Here (NA_K (SInt a) :* NP0)) sfrom' SZ (El []) = Rep $ Here NP0 sfrom' SZ (El (x:xs)) = Rep $ There (Here (NA_I (El x) :* NA_I (El xs) :* NP0)) sfrom' _ _ = error "unreachable" sto' SZ (Rep (Here NP0)) = El [] sto' SZ (Rep (There (Here (NA_I (El x) :* NA_I (El xs) :* NP0)))) = El (x : xs) sto' (SS SZ) (Rep (Here (NA_K (SInt a) :* NA_I (El as) :* NP0))) = El (a :>: as) sto' (SS SZ) (Rep (There (Here (NA_K (SInt a) :* NP0)))) = El (Leaf a) sto' _ _ = error "unreachable" instance HasDatatypeInfo Singl FamRose CodesRose where datatypeInfo _ SZ = ADT "module" (Name "[]" :@: (Name "R" :@: Name "Int")) $ (Constructor "[]") :* (Infix ":" RightAssociative 5) :* NP0 datatypeInfo _ (SS SZ) = ADT "module" (Name "R" :@: Name "Int") $ (Infix ":>:" NotAssociative 0) :* (Constructor "Leaf") :* NP0 datatypeInfo _ _ = error "unreachable" -- * Eq Instance instance Eq (R Int) where (==) = geq eqSingl `on` (into @FamRose) testEq :: Bool testEq = value1 == value1 && value2 /= value1 -- * Compos test pattern RInt_ = SS SZ normalize :: R Int -> R Int normalize = unEl . go (SS SZ) . into where go :: forall iy. (IsNat iy) => SNat iy -> El FamRose iy -> El FamRose iy go RInt_ (El (Leaf a)) = El (a :>: []) go _ x = compos go x -- * Crush test sumTree :: R Int -> Int sumTree = crush k sum . (into @FamRose) where k :: Singl x -> Int k (SInt n) = n testSum :: Bool testSum = sumTree value3 == sumTree (normalize value3)