@@ -0,0 +1,70 @@
1+{-# LANGUAGE TypeFamilies #-}
2+
3+module Main where
4+
5+import Prelude hiding (lookup)
6+import Data.Char (ord)
7+import qualified Data.Map as Map
8+
9+
10+-- Generic maps as ATs
11+-- -------------------
12+
13+class GMapKey k where
14+ data GMap k :: * -> *
15+ empty :: GMap k v
16+ lookup :: k -> GMap k v -> Maybe v
17+ insert :: k -> v -> GMap k v -> GMap k v
18+
19+instance GMapKey Int where
20+ data GMap Int v = GMapInt (Map.Map Int v)
21+ empty = GMapInt Map.empty
22+ lookup k (GMapInt m) = Map.lookup k m
23+ insert k v (GMapInt m) = GMapInt (Map.insert k v m)
24+
25+instance GMapKey Char where
26+ data GMap Char v = GMapChar (GMap Int v)
27+ empty = GMapChar empty
28+ lookup k (GMapChar m) = lookup (ord k) m
29+ insert k v (GMapChar m) = GMapChar (insert (ord k) v m)
30+
31+instance GMapKey () where
32+ data GMap () v = GMapUnit (Maybe v)
33+ empty = GMapUnit Nothing
34+ lookup () (GMapUnit v) = v
35+ insert () v (GMapUnit _) = GMapUnit $ Just v
36+
37+instance (GMapKey a, GMapKey b) => GMapKey (a, b) where
38+ data GMap (a, b) v = GMapPair (GMap a (GMap b v))
39+ empty = GMapPair empty
40+ lookup (a, b) (GMapPair gm) = lookup a gm >>= lookup b
41+ insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of
42+ Nothing -> insert a (insert b v empty) gm
43+ Just gm2 -> insert a (insert b v gm2 ) gm
44+
45+instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where
46+ data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)
47+ empty = GMapEither empty empty
48+ lookup (Left a) (GMapEither gm1 _gm2) = lookup a gm1
49+ lookup (Right b) (GMapEither _gm1 gm2 ) = lookup b gm2
50+ insert (Left a) v (GMapEither gm1 gm2) = GMapEither (insert a v gm1) gm2
51+ insert (Right a) v (GMapEither gm1 gm2) = GMapEither gm1 (insert a v gm2)
52+
53+-- Test code
54+-- ---------
55+
56+nonsence :: GMap Bool String
57+nonsence = undefined
58+
59+-- a combinator!! cool!
60+--
61+myGMap :: GMap (Int, Either Char ()) String
62+myGMap = insert (5, Left 'c') "(5, Left 'c')" $
63+ insert (4, Right ()) "(4, Right ())" $
64+ insert (5, Right ()) "This is the one!" $
65+ insert (5, Right ()) "This is the two!" $
66+ insert (6, Right ()) "(6, Right ())" $
67+ insert (5, Left 'a') "(5, Left 'a')" $
68+ empty
69+main = putStrLn $ maybe "Couldn't find key!" id $ lookup (5, Right ()) myGMap
70+