diff --git a/limp.cabal b/limp.cabal
--- a/limp.cabal
+++ b/limp.cabal
@@ -1,5 +1,5 @@
 name:                limp
-version:             0.3.2.1
+version:             0.3.2.2
 synopsis:            representation of Integer Linear Programs
 description:         so far, this package just provides two representations for linear programs: "Numeric.Limp.Program", which is what I expect end-users to use, and
                      "Numeric.Limp.Canon", which is simpler, but would be less nice for writing linear programs.
@@ -53,7 +53,7 @@
         Numeric.Limp.Solve.Branch.Simple
 
   build-depends:
-        base        < 5,
+        base        >= 4.9 && < 5,
         containers  == 0.5.*
 
   ghc-options: -Wall -fno-warn-orphans
@@ -85,4 +85,3 @@
 
   default-language: Haskell2010
   default-extensions:       TemplateHaskell TypeFamilies FlexibleContexts GeneralizedNewtypeDeriving DataKinds GADTs RankNTypes StandaloneDeriving FlexibleInstances
-
diff --git a/src/Numeric/Limp/Canon/Convert.hs b/src/Numeric/Limp/Canon/Convert.hs
--- a/src/Numeric/Limp/Canon/Convert.hs
+++ b/src/Numeric/Limp/Canon/Convert.hs
@@ -12,7 +12,6 @@
 import qualified Numeric.Limp.Program.Linear     as P
 import qualified Numeric.Limp.Program.Program    as P
 
-import Control.Applicative
 import qualified Data.Map as M
 
 
diff --git a/src/Numeric/Limp/Canon/Program.hs b/src/Numeric/Limp/Canon/Program.hs
--- a/src/Numeric/Limp/Canon/Program.hs
+++ b/src/Numeric/Limp/Canon/Program.hs
@@ -55,7 +55,7 @@
 
 checkBounds :: (Rep c, Ord z, Ord r) => Assignment z r c -> Map (Either z r) (Maybe (R c), Maybe (R c)) -> Bool
 checkBounds ass bs
- =  M.fold (&&) True (M.mapWithKey checkB bs)
+ =  M.foldr (&&) True (M.mapWithKey checkB bs)
  where
   checkB k (lo,up)
    = let v = zrOf ass k
diff --git a/src/Numeric/Limp/Canon/Simplify.hs b/src/Numeric/Limp/Canon/Simplify.hs
--- a/src/Numeric/Limp/Canon/Simplify.hs
+++ b/src/Numeric/Limp/Canon/Simplify.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 -- | Perform some simple optimisations on program
 module Numeric.Limp.Canon.Simplify where
 import Numeric.Limp.Canon.Program
@@ -10,7 +11,9 @@
 import Numeric.Limp.Canon.Simplify.Crunch
 import Numeric.Limp.Canon.Simplify.Subst
 
-import Data.Monoid
+#if MIN_VERSION_base(4,9,0) && !MIN_VERSION_base(4,11,0)
+import Data.Semigroup
+#endif
 
 simplify :: (Ord z, Ord r, Rep c) => Program z r c -> Either Infeasible (Assignment z r c, Program z r c)
 simplify p
diff --git a/src/Numeric/Limp/Canon/Simplify/Bounder.hs b/src/Numeric/Limp/Canon/Simplify/Bounder.hs
--- a/src/Numeric/Limp/Canon/Simplify/Bounder.hs
+++ b/src/Numeric/Limp/Canon/Simplify/Bounder.hs
@@ -6,7 +6,6 @@
 import Numeric.Limp.Rep
 import Numeric.Limp.Error
 
-import Control.Applicative
 import Data.Either
 import qualified Data.Map as M
 
diff --git a/src/Numeric/Limp/Program/Constraint.hs b/src/Numeric/Limp/Program/Constraint.hs
--- a/src/Numeric/Limp/Program/Constraint.hs
+++ b/src/Numeric/Limp/Program/Constraint.hs
@@ -1,9 +1,12 @@
+{-# LANGUAGE CPP #-}
 module Numeric.Limp.Program.Constraint where
 import Numeric.Limp.Program.Linear
 import Numeric.Limp.Program.ResultKind
 import Numeric.Limp.Rep
 
-import Data.Monoid
+#if MIN_VERSION_base(4,9,0) && !MIN_VERSION_base(4,11,0)
+import Data.Semigroup
+#endif
 
 -- | Different kind of constraints.
 --
@@ -22,7 +25,7 @@
 --   [@:>@]     Strictly greater than: this is only allowed for purely integer functions
 --
 --   [@Between@] @Between a b c@ is equivalent to @a :<= b :&& b :<= c@
--- 
+--
 --   [@:&&@]    Conjunction of two constraints
 --
 --   [@:!@]     @"name" :! constr@ Annotate a constraint with a name, or other useless information
@@ -33,9 +36,9 @@
 data Constraint z r c where
  (:==)   :: Linear z r c k1  -> Linear z r c k2  -> Constraint z r c
  (:<=)   :: Linear z r c k1  -> Linear z r c k2  -> Constraint z r c
- (:<)    :: Linear z r c KZ  -> Linear z r c KZ  -> Constraint z r c
+ (:<)    :: Linear z r c 'KZ -> Linear z r c 'KZ -> Constraint z r c
  (:>=)   :: Linear z r c k1  -> Linear z r c k2  -> Constraint z r c
- (:>)    :: Linear z r c KZ  -> Linear z r c KZ  -> Constraint z r c
+ (:>)    :: Linear z r c 'KZ -> Linear z r c 'KZ -> Constraint z r c
  Between :: Linear z r c k1  -> Linear z r c k2  -> Linear z r c k3   -> Constraint z r c
  (:&&)   :: Constraint z r c -> Constraint z r c -> Constraint z r c
  (:!)    :: String           -> Constraint z r c -> Constraint z r c
@@ -51,7 +54,9 @@
 infix  4 :!
 infixr 3 :&&
 
+instance Semigroup (Constraint z r c) where
+ (<>) = (:&&)
+
 instance Monoid (Constraint z r c) where
  mempty  = CTrue
  mappend = (:&&)
-
diff --git a/src/Numeric/Limp/Program/Linear.hs b/src/Numeric/Limp/Program/Linear.hs
--- a/src/Numeric/Limp/Program/Linear.hs
+++ b/src/Numeric/Limp/Program/Linear.hs
@@ -22,7 +22,7 @@
 import Numeric.Limp.Program.ResultKind
 
 -- | Any linear function can be converted into a real linear function.
-toR :: Rep c => Linear z r c k -> Linear z r c KR
+toR :: Rep c => Linear z r c k -> Linear z r c 'KR
 toR (LZ ls co) = LR (map go ls) (fromZ co)
  where
   go (z',c') = (Left z', fromZ c')
@@ -30,44 +30,44 @@
 
 
 -- | Integral variable
-z :: Rep c => z -> Z c -> Linear z r c KZ
+z :: Rep c => z -> Z c -> Linear z r c 'KZ
 z z' c
  = LZ [(z', c)] 0
 
 -- | Integral variable with coefficient 1
-z1 :: Rep c => z -> Linear z r c KZ
+z1 :: Rep c => z -> Linear z r c 'KZ
 z1 z'
  = z z' 1
 
 -- | Real variable
-r :: Rep c => r -> R c -> Linear z r c KR
+r :: Rep c => r -> R c -> Linear z r c 'KR
 r r' c
  = LR [(Right r', c)] 0
 
 -- | Real variable with coefficient 1
-r1 :: Rep c => r -> Linear z r c KR
+r1 :: Rep c => r -> Linear z r c 'KR
 r1 r'
  = r r' 1
 
 
 -- | An integral constant summand
-con :: Rep c => Z c -> Linear z r c KZ
+con :: Rep c => Z c -> Linear z r c 'KZ
 con c'
  = LZ [] c'
 
 -- | An integral constant summand
-conZ :: Rep c => Z c -> Linear z r c KZ
+conZ :: Rep c => Z c -> Linear z r c 'KZ
 conZ = con
 
 -- | Constant @0@
-c0 :: Rep c => Linear z r c KZ
+c0 :: Rep c => Linear z r c 'KZ
 c0 = con 0
 -- | Constant @1@
-c1 :: Rep c => Linear z r c KZ
+c1 :: Rep c => Linear z r c 'KZ
 c1 = con 1
 
 -- | A real constant
-conR :: Rep c => R c -> Linear z r c KR
+conR :: Rep c => R c -> Linear z r c 'KR
 conR c'
  = LR [] c'
 
@@ -107,10 +107,10 @@
     (LZ{}, LR{}) -> add_KR (toR a)     b
     (LR{}, LR{}) -> add_KR      a      b
  where
-  add_KZ :: Rep c => Linear z r c KZ -> Linear z r c KZ -> Linear z r c KZ
+  add_KZ :: Rep c => Linear z r c 'KZ -> Linear z r c 'KZ -> Linear z r c 'KZ
   add_KZ (LZ ls lc) (LZ rs rc) = LZ (ls ++ rs) (lc + rc)
 
-  add_KR :: Rep c => Linear z r c KR -> Linear z r c KR -> Linear z r c KR
+  add_KR :: Rep c => Linear z r c 'KR -> Linear z r c 'KR -> Linear z r c 'KR
   add_KR (LR ls lc) (LR rs rc) = LR (ls ++ rs) (lc + rc)
 
 
diff --git a/src/Numeric/Limp/Program/Program.hs b/src/Numeric/Limp/Program/Program.hs
--- a/src/Numeric/Limp/Program/Program.hs
+++ b/src/Numeric/Limp/Program/Program.hs
@@ -24,7 +24,7 @@
    -- | Optimisation direction
      _direction     :: Direction
    -- | The objective function
-   , _objective     :: Linear z r c KR
+   , _objective     :: Linear z r c 'KR
    -- | All constraints bundled up with @:&&@.
    , _constraints   :: Constraint z r c
    -- | Upper and lower bounds of variables.
diff --git a/src/Numeric/Limp/Program/ResultKind.hs b/src/Numeric/Limp/Program/ResultKind.hs
--- a/src/Numeric/Limp/Program/ResultKind.hs
+++ b/src/Numeric/Limp/Program/ResultKind.hs
@@ -18,8 +18,8 @@
 -- | Representation of either integral of real linear functions:
 -- a list of variables with coefficients, plus a constant summand.
 data Linear z r c k where
- LZ :: [(z, Z c)]          -> (Z c) -> Linear z r c KZ
- LR :: [(Either z r, R c)] -> (R c) -> Linear z r c KR
+ LZ :: [(z, Z c)]          -> (Z c) -> Linear z r c 'KZ
+ LR :: [(Either z r, R c)] -> (R c) -> Linear z r c 'KR
 
 deriving instance (Show z, Show r, Show (Z c), Show (R c)) => (Show (Linear z r c k))
 
@@ -27,14 +27,14 @@
 -- | Find the result type of merging, or adding, two linear functions:
 -- adding two integers produces an integer, while adding a real on either side produces a real.
 type family KMerge (a :: K) (b :: K) :: K where
- KMerge KZ KZ = KZ
- KMerge KR b  = KR
- KMerge a  KR = KR
+ KMerge 'KZ 'KZ = 'KZ
+ KMerge 'KR  b  = 'KR
+ KMerge  a  'KR = 'KR
 
 -- | Convert a @K@ to its actual representation (@Z@ or @R@).
 type family KRep (a :: K) :: * -> * where
- KRep KZ = Z
- KRep KR = R
+ KRep 'KZ = Z
+ KRep 'KR = R
 
 
 
diff --git a/src/Numeric/Limp/Rep/Rep.hs b/src/Numeric/Limp/Rep/Rep.hs
--- a/src/Numeric/Limp/Rep/Rep.hs
+++ b/src/Numeric/Limp/Rep/Rep.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 -- | Representation of integers (Z) and reals (R) of similar precision.
 -- Programs are abstracted over this, so that ideally in the future we could have a
 -- solver that produces Integers and Rationals, instead of just Ints and Doubles.
@@ -10,7 +11,9 @@
 import Data.Map (Map)
 import qualified Data.Map as M
 
-import Data.Monoid
+#if MIN_VERSION_base(4,9,0) && !MIN_VERSION_base(4,11,0)
+import Data.Semigroup
+#endif
 
 -- | The Representation class. Requires its members @Z c@ and @R c@ to be @Num@, @Ord@ and @Eq@.
 --
@@ -38,6 +41,9 @@
 
 deriving instance (Show (Z c), Show (R c), Show z, Show r) => Show (Assignment z r c)
 
+instance (Ord z, Ord r) => Semigroup (Assignment z r c) where
+ (<>) = mappend
+
 instance (Ord z, Ord r) => Monoid (Assignment z r c) where
  mempty = Assignment M.empty M.empty
  mappend (Assignment z1 r1) (Assignment z2 r2)
@@ -61,4 +67,3 @@
 assSize :: Assignment z r c -> Int
 assSize (Assignment mz mr)
  = M.size mz + M.size mr
-
diff --git a/src/Numeric/Limp/Solve/Branch/Simple.hs b/src/Numeric/Limp/Solve/Branch/Simple.hs
--- a/src/Numeric/Limp/Solve/Branch/Simple.hs
+++ b/src/Numeric/Limp/Solve/Branch/Simple.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 -- | The simplest, stupidest possible branch and bound algorithm.
 --
 --
@@ -8,10 +9,12 @@
 import Numeric.Limp.Canon.Simplify
 import Numeric.Limp.Rep
 
-import Control.Applicative
 import Control.Monad
 import qualified Data.Map as M
-import Data.Monoid
+
+#if MIN_VERSION_base(4,9,0) && !MIN_VERSION_base(4,11,0)
+import Data.Semigroup
+#endif
 
 branch
     :: (Ord z, Ord r, Rep c)
diff --git a/src/Numeric/Limp/Solve/Simplex/Maps.hs b/src/Numeric/Limp/Solve/Simplex/Maps.hs
--- a/src/Numeric/Limp/Solve/Simplex/Maps.hs
+++ b/src/Numeric/Limp/Solve/Simplex/Maps.hs
@@ -249,7 +249,7 @@
   rs'     = M.map eval $ _substs s
 
   eval (lin,co)
-          = M.fold (+) co
+          = M.foldr (+) co
           $ M.mapWithKey (\k r -> r * (maybe 0 id $ M.lookup k vs))
           $ lin
 
@@ -281,7 +281,7 @@
         => Standard z r c -> Standard z r c
 pricing_out s
  = s
- { _objective = M.foldWithKey  go
+ { _objective = M.foldrWithKey  go
                     (_objective   s)
                     (_constraints s)
  }
