```{- |
some queries implemented using operations from relational algebra
-}
module Example.RelationalAlgebra where

import Query
import Company

import qualified Data.Map as Map
import Data.Maybe (isNothing, )
import qualified Data.Tree as Tree

{- |
all employees
-}
employees :: [Emp]
employees = emp

{- |
all clerks
-}
clerks :: [Emp]
clerks =
filter (\e -> job e == Clerk) emp

{- |
all clerks with salary at least 1000
-}
richClerks :: [Emp]
richClerks =
filter (\e -> job e == Clerk && sal e >= 1000) emp

{- |
all employees in research department
-}
researchers :: [Emp]
researchers =
map fst
(filter (\(e,d) -> deptno e == deptno d && dname d == "RESEARCH")
(cross emp dept))

researchers0 :: [Emp]
researchers0 =
map snd
(filter (\(d,e) -> deptno e == deptno d)
(cross (filter (\d -> dname d == "RESEARCH") dept) emp))

hierarchy :: Tree.Forest Emp
hierarchy =
let emptrees =
map (\e -> Tree.Node e (filter ((Just (empno e) ==) . mgr . Tree.rootLabel) emptrees)) emp
in  filter (isNothing . mgr . Tree.rootLabel) emptrees
{-
putStr \$ Tree.drawForest \$ map (fmap ename) hierarchy
-}

hierarchyFast :: Tree.Forest Emp
hierarchyFast =
let emptrees =
Map.fromListWith (++) \$
map
(\e -> (mgr e, [Tree.Node e (Map.findWithDefault [] (Just (empno e)) emptrees)]))
emp
in  Map.findWithDefault [] Nothing emptrees

{- |
A recursive query:
Compute the total salary for each manager
and the total set of employees he conducts.
-}
teamSalaries :: [(String, Int)]
teamSalaries =
let recurse (Tree.Node e sub0) =
let sub1 = map recurse sub0
in  Tree.Node (ename e, sal e + sum (map (snd . Tree.rootLabel) sub1)) sub1
in  Tree.flatten =<< map recurse hierarchyFast
```