alloy-1.0.0: tutorial/MapSetExample.lhs
We can now use these instances to perform some operations on the data types.
First, we will define some operations to derive the \lstinline|CompanyInfo|
information, using a state monad:
\begin{code}
import CompanyDatatypes
import MapSet
import MapSetInstances
import Data.Generics.Alloy
import qualified Data.Map as Map
import qualified Data.Set as Set
import Control.Monad.State
companyInfo :: Company -> CompanyInfo
companyInfo c = execState (applyBottomUpM2 doEmployee doDept c)
(CompanyInfo Map.empty Set.empty)
where
doEmployee :: Employee -> State CompanyInfo Employee
doEmployee (E p s)
= do modify $ \(CompanyInfo es ms) ->
CompanyInfo (Map.insert p s es) ms
return (E p s)
doDept :: Dept -> State CompanyInfo Dept
doDept d@(D _ m _)
= do modify $ \(CompanyInfo es ms) ->
CompanyInfo es (Set.insert m ms)
return d
\end{code}
We can then perform further operations on the \lstinline|CompanyInfo| type.
For example, we can increase the salary of all employees with the letter `o'
in their name:
\begin{code}
incS :: Float -> Salary -> Salary
incS k (S s) = S (s * (1+k))
increaseOs :: Float -> CompanyInfo -> CompanyInfo
increaseOs k = applyBottomUp inc
where
inc :: (Person, Salary) -> (Person, Salary)
inc (P n a, s)
| 'o' `elem` n = (P n a, incS k s)
| otherwise = (P n a, s)
main = print $ increaseOs 0.1 $ companyInfo genCom
\end{code}
Notice how we define the function to work on key-value pairs in order to
process the map entries. If you wish to process the map itself differently,
you can define an operation on the map; the map instances we use here are
particularly useful for descending into maps (for example if the value in a
map can contain types you wish to process).