-- Uses a record where the type of the fields are inferred {-# LANGUAGE GADTs, MagicHash #-} module RecordTest where import Data.Monoid import Data.IntMap(IntMap) import qualified Data.IntMap as IntMap import qualified GHC.Prim as Prim -- Represents a field of the record data Field a = Field !Int (k1) = Field 1 -- k1 :: Field Bool (k2) = Field 2 -- k2 :: Field String -- Record with a list of values for each field data Record = Record !(IntMap [Prim.Any]) single :: Field a -> a -> Record single (Field k) = Record . IntMap.singleton k . return . Prim.unsafeCoerce# index :: Field a -> Record -> [a] index (Field k) (Record mp) = map Prim.unsafeCoerce# $ IntMap.findWithDefault [] k mp instance Monoid Record where mempty = Record IntMap.empty (Record mp1) `mappend` (Record mp2) = Record mp3 where mp3 = IntMap.unionWith (++) mp1 mp2 -- Some two traversals trav1 :: [Int] -> Record trav1 = foldr add mempty where add x r | even x = single k1 True `mappend` r | odd x = single k2 (show x) `mappend` r trav2 :: Record -> [Int] -> ([Bool], [String]) trav2 r = foldr add ([],[]) where add _ (b1,s1) = (b1 ++ index k1 r, s1 ++ index k2 r) -- Test list :: [Int] list = [1..4] t :: ([Bool], [String]) t = trav2 (trav1 list) list