{-# OPTIONS -fglasgow-exts #-}
module Ext1 (tests) where
import Test.HUnit
import Data.Generics
import GHC.Base
unsafeCoerce :: a -> b
unsafeCoerce = unsafeCoerce#
newtype ID x = ID { unID :: x }
newtype CONST c a = CONST { unCONST :: c }
extListQ' :: Data d
=> (d -> q)
-> (forall d. [d] -> q)
-> d -> q
extListQ' def ext d =
if isList d
then ext (unsafeCoerce d)
else def d
foo1 :: Data d => d -> Int
foo1 = const 0 `extListQ'` length
t1 = foo1 True
t2 = foo1 [True,True]
extListQ'' :: Data d
=> (d -> q)
-> (forall d. Data d => [d] -> q)
-> d -> q
extListQ'' def ext d =
if isList d
then undefined
else def d
foo2 :: Data a => a -> Int
foo2 = const 0 `ext1Q` list
where
list :: Data a => [a] -> Int
list l = foldr (+) 0 $ map glength l
t3 = foo2 (True,True)
t4 = foo2 [(True,True),(True,True)]
foo3 :: Data a => a -> Int
foo3 x = if isList x
then foldr (+) 0 $ gmapListQ glength x
else 0
t5 = foo3 (True,True)
t6 = foo3 [(True,True),(True,True)]
isList :: Data a => a -> Bool
isList x = typeRepTyCon (typeOf x) ==
typeRepTyCon (typeOf (undefined::[()]))
isNil :: Data a => a -> Bool
isNil x = toConstr x == toConstr ([]::[()])
isCons :: Data a => a -> Bool
isCons x = toConstr x == toConstr (():[])
gmapListQ :: forall a q. Data a => (forall a. Data a => a -> q) -> a -> [q]
gmapListQ f x =
if not $ isList x
then error "gmapListQ"
else if isNil x
then []
else if isCons x
then ( gmapQi 0 f x : gmapQi 1 (gmapListQ f) x )
else error "gmapListQ"
mkNil :: Data a => a
mkNil = fromConstr $ toConstr ([]::[()])
mkCons :: Data a => a
mkCons = fromConstr $ toConstr ((undefined:undefined)::[()])
tests = ( t1
, ( t2
, ( t3
, ( t4
, ( t5
, ( t6
)))))) ~=? output
output = (0,(2,(0,(4,(0,4)))))