packages feed

one-liner-0: examples/paradise.hs

{-# LANGUAGE 
    TypeFamilies
  , ConstraintKinds
  , FlexibleInstances
  , DefaultSignatures
  , OverlappingInstances
  , TypeSynonymInstances
  #-}

import Generics.OneLiner.ADT
import Control.Applicative


data Company  = C [Dept]               deriving (Eq, Read, Show)               
data Dept     = D Name Manager [Unit]  deriving (Eq, Read, Show)
data Unit     = PU Employee | DU Dept  deriving (Eq, Read, Show)
data Employee = E Person Salary        deriving (Eq, Read, Show)
data Person   = P Name Address         deriving (Eq, Read, Show)
data Salary   = S Float                deriving (Eq, Read, Show)                  
type Manager  = Employee 
type Name     = String
type Address  = String

-- An illustrative company
genCom :: Company
genCom = C [D "Research" laemmel [PU joost, PU marlow],
            D "Strategy" blair   []]

laemmel, joost, marlow, blair :: Employee
laemmel = E (P "Laemmel" "Amsterdam") (S 8000)
joost   = E (P "Joost"   "Amsterdam") (S 1000)
marlow  = E (P "Marlow"  "Cambridge") (S 2000)
blair   = E (P "Blair"   "London")    (S 100000)


instance ADT Company where
  type Constraints Company c = c [Dept]
  buildsA For f = [(ctor "C", C <$> f (FieldInfo $ \(C l) -> l))]

instance ADT Dept where
  type Constraints Dept c = (c Name, c Manager, c [Unit])
  buildsA For f = [(ctor "D", D 
    <$> f (FieldInfo $ \(D n _ _) -> n) 
    <*> f (FieldInfo $ \(D _ m _) -> m) 
    <*> f (FieldInfo $ \(D _ _ u) -> u))]

instance ADT Unit where
  ctorIndex PU{} = 0
  ctorIndex DU{} = 1
  type Constraints Unit c = (c Employee, c Dept)
  buildsA For f = 
    [ (ctor "PU", PU <$> f (FieldInfo $ \(PU e) -> e))
    , (ctor "DU", DU <$> f (FieldInfo $ \(DU d) -> d))
    ]

instance ADT Employee where
  type Constraints Employee c = (c Person, c Salary)
  buildsA For f = [(ctor "E", E <$> f (FieldInfo $ \(E p _) -> p) <*> f (FieldInfo $ \(E _ s) -> s))]

instance ADT Person where
  type Constraints Person c = (c Name, c Address)
  buildsA For f = [(ctor "P", P <$> f (FieldInfo $ \(P n _) -> n) <*> f (FieldInfo $ \(P _ a) -> a))]

instance ADT Salary where
  type Constraints Salary c = (c Float)
  buildsA For f = [(ctor "S", S <$> f (FieldInfo $ \(S s) -> s))]

  
class IncreaseSalary t where
  increaseSalary :: Float -> t -> t
  default increaseSalary :: (ADT t, Constraints t IncreaseSalary) => Float -> t -> t
  increaseSalary k = gmap (For :: For IncreaseSalary) (increaseSalary k)

instance IncreaseSalary Company
instance IncreaseSalary Dept
instance IncreaseSalary Unit
instance IncreaseSalary Employee
instance IncreaseSalary Person
instance IncreaseSalary Salary where
  increaseSalary k (S s) = S (s * (1+k))
instance IncreaseSalary a => IncreaseSalary [a]
instance IncreaseSalary String where
  increaseSalary _ = id
  
main :: IO ()
main = print $ increaseSalary 0.1 genCom