-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathMapping.hs
94 lines (69 loc) · 2.62 KB
/
Mapping.hs
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
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
module Mapping
( Numbered (..)
, o
, unNumbered
, number
, Traversable ()
, Mapping (..)
, prodMap
, lookupNumMap
, lookupNumMap'
, NumMap) where
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import Data.Traversable
import Data.Foldable
import Control.Monad.State hiding (mapM)
import Prelude hiding (mapM)
-- | This type is used for numbering components of a functorial value.
data Numbered a = Numbered Int a
unNumbered :: Numbered a -> a
unNumbered (Numbered _ x) = x
-- | This function numbers the components of the given functorial
-- value with consecutive integers starting at 0.
number :: Traversable f => f c -> f (Numbered c)
number x = evalState (mapM run x) 0 where
run :: c -> State Int (Numbered c)
run b = do n <- get
put (n+1)
return $ Numbered n b
infix 1 |->
infixr 0 &
class Traversable m => Mapping m k | m -> k where
-- | left-biased union of two mappings.
(&) :: m v -> m v -> m v
-- | This operator constructs a singleton mapping.
(|->) :: k -> v -> m v
-- | This is the empty mapping.
empty :: m v
-- | This function constructs the pointwise product of two maps each
-- with a default value.
prodMapWith :: (v1 -> v2 -> v) -> v1 -> v2 -> m v1 -> m v2 -> m v
-- | Returns the value at the given key or returns the given
-- default when the key is not an element of the map.
findWithDefault :: a -> k -> m a -> a
o :: Mapping m k => m v
o = empty
-- | This function constructs the pointwise product of two maps each
-- with a default value.
prodMap :: Mapping m k => v1 -> v2 -> m v1 -> m v2 -> m (v1, v2)
prodMap = prodMapWith (,)
newtype NumMap k v = NumMap (IntMap v) deriving (Functor, Foldable, Traversable)
lookupNumMap :: a -> Int -> NumMap t a -> a
lookupNumMap d k (NumMap m) = IntMap.findWithDefault d k m
lookupNumMap' :: Int -> NumMap t a -> Maybe a
lookupNumMap' k (NumMap m) = IntMap.lookup k m
instance Mapping (NumMap k) (Numbered k) where
NumMap m1 & NumMap m2 = NumMap (IntMap.union m1 m2)
Numbered k _ |-> v = NumMap $ IntMap.singleton k v
empty = NumMap IntMap.empty
findWithDefault d (Numbered i _) m = lookupNumMap d i m
prodMapWith f p q (NumMap mp) (NumMap mq) = NumMap $ IntMap.mergeWithKey merge
(IntMap.map (`f` q)) (IntMap.map (p `f`)) mp mq
where merge _ p q = Just (p `f` q)