diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,13 @@
+0.9.2.1:
+
+  Updated the minimum base package to 4.5.0.0 (GHC 7.4.1), and removed
+  some old code for supporting older GHC/package versions. There are
+  some warnings when compiling with GHC pre version 8 (redudant imports)
+  which I am currently too lazy to fix, but patches are welcome. Support
+  for building with older versions of GHC is on a best-effort basis.
+  Applied some HLint suggestions. Updated to allow time-1.9.1 (but not
+  time-1.9.0). Updated to lts 11.1 in stack.yaml.
+
 0.9.2.0:
 
   Initial support for ghc 8.4. Updated to lts 10.8 in stack.yaml so
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,8 +1,4 @@
 
-![Build Status](https://drone.io/bitbucket.org/doug_burke/swish/status.png)
-
-[drone.io status page](https://drone.io/bitbucket.org/doug_burke/swish)
-
 # Introduction
 
 Swish - which stands for Semantic Web Inference Scripting in Haskell -
@@ -26,9 +22,12 @@
 functions. Development is done on the [bitbucket
 site](https://bitbucket.org/doug_burke/swish/); there is an *outdated*
 version [on GitHub](https://github.com/DougBurke/swish), which was
-being used for its access to Travis, but now I use [drone.io for
-build/testing](https://drone.io/bitbucket.org/doug_burke/swish).
+being used for its access to Travis.
 
+I attempt to keep Swish buildable on recent GHC versions - at present
+back to GHC 7.4 - but it is done on a best-effort basis, so is not
+guaranteed.
+
 # Aim
 
 Current development is based on my own needs, which are more about
@@ -40,7 +39,7 @@
 
     (c) 2003, 2004 G. Klyne
     (c) 2009 Vasili I Galchin
-    (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 Doug Burke
+    (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Doug Burke
 
 All rights reserved.
 
@@ -58,12 +57,25 @@
 
 # Installation
 
+The following commands will install a command-line tool `Swish` along
+with the modules in the `Swish` namespace; documentation can be found 
+[on Hackage](http://hackage.haskell.org/package/swish).
+
+## With cabal
+
 Install a recent version of the [Haskell
 platform](http://hackage.haskell.org/platform/) and then try
 
     % cabal update
     % cabal install swish
 
-This will install a command-line tool `Swish` along with the modules
-in the `Swish` namespace; documentation can be found 
-[on Hackage](http://hackage.haskell.org/package/swish).
+## With stack
+
+There are several stack configuration files, for different GHC
+versions:
+
+    % cd swish
+    % stack install
+    % STACK_YAML=stack-8.0.yaml stack install
+    % STACK_YAML=stack-7.10.yaml stack install
+    % STACK_YAML=stack-7.8.yaml stack install
diff --git a/src/Swish/Datatype.hs b/src/Swish/Datatype.hs
--- a/src/Swish/Datatype.hs
+++ b/src/Swish/Datatype.hs
@@ -7,7 +7,7 @@
 -- |
 --  Module      :  Datatype
 --  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---                 2011, 2012 Douglas Burke
+--                 2011, 2012, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
@@ -71,7 +71,8 @@
 --
 -- import Swish.Utils.ShowM (ShowM(..))
 
-import Control.Monad (join, liftM)
+import Control.Applicative ((<$>))
+import Control.Monad (join)
 
 import Data.Maybe (isJust, catMaybes)
 
@@ -252,7 +253,7 @@
     where
       dtmap = tvalMap dtv
       val   = mapL2V dtmap str
-      can   = join $ liftM (mapV2L dtmap) val
+      can   = join $ fmap (mapV2L dtmap) val
 
 -- |DatatypeMap consists of methods that perform lexical-to-value
 --  and value-to-canonical-lexical mappings for a datatype.
@@ -787,7 +788,7 @@
         cvals2 = sequence $ mergeTupleVals (map fst fnss) args cvals1
         --  Map list of alternative values for each tuple member to
         --  a list of alternative tuples.
-        cvals3 = liftM sequence cvals2
+        cvals3 = fmap sequence cvals2
         --  Check each tuple against the supplied predicate.
         --  If any of the alternative tuples does not match the predicate
         --  then signal an inconsistency.
@@ -821,7 +822,7 @@
     ((vt->Bool)->b->[Maybe vt]->Maybe [vt]) -> (vt->Bool,[b]) -> [Maybe vt]
     -> Maybe [vt]
 applyFdescToTuple apfn (p,fns) args =
-    liftM concat $ sequence cvals
+    concat <$> sequence cvals
     where
         -- cvals :: [Maybe [vt]]
         cvals = flist (map (apfn p) fns) args
@@ -1036,7 +1037,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012 Douglas Burke
+--    2011, 2012, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/GraphMatch.hs b/src/Swish/GraphMatch.hs
--- a/src/Swish/GraphMatch.hs
+++ b/src/Swish/GraphMatch.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 
@@ -8,12 +7,12 @@
 -- |
 --  Module      :  GraphMatch
 --  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---                 2011, 2012, 2016 Douglas Burke
+--                 2011, 2012, 2016, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  CPP, FlexibleInstances, MultiParamTypeClasses
+--  Portability :  FlexibleInstances, MultiParamTypeClasses
 --
 --  This module contains graph-matching logic.
 --
@@ -564,12 +563,7 @@
 -- Replace the values in lm1 with those from lm2, but do not copy over new
 -- keys from lm2
 classifyCombine :: (Ord a) => M.Map a b -> M.Map a b -> M.Map a b
-#if MIN_VERSION_containers(0,5,0)
 classifyCombine = M.mergeWithKey (\_ _ v -> Just v) id (const M.empty)
-#else
--- rely on the left-biased nature of union
-classifyCombine lm1 lm2 = M.intersection lm2 lm1 `M.union` lm1
-#endif
 
 -- | Calculate a new index value for a supplied set of labels based on the
 --  supplied label map and adjacency calculations in the supplied graph
@@ -677,7 +671,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012 Douglas Burke
+--    2011, 2012, 2016, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/RDF/ClassRestrictionRule.hs b/src/Swish/RDF/ClassRestrictionRule.hs
--- a/src/Swish/RDF/ClassRestrictionRule.hs
+++ b/src/Swish/RDF/ClassRestrictionRule.hs
@@ -7,7 +7,7 @@
 -- |
 --  Module      :  ClassRestrictionRule
 --  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---                 2011, 2012, 2014 Douglas Burke
+--                 2011, 2012, 2014, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
@@ -57,7 +57,7 @@
 import Swish.RDF.VarBinding (RDFVarBinding)
 import Swish.RDF.Vocabulary (namespaceRDFD)
 
-import Control.Monad (liftM)
+import Control.Applicative ((<$>))
 
 import Data.List (delete, nub, subsequences)
 import Data.Maybe (fromJust, fromMaybe, mapMaybe)
@@ -118,7 +118,7 @@
 makeDatatypeRestrictionFn ::
     RDFDatatypeVal vt -> DatatypeRelFn vt -> ClassRestrictionFn
 makeDatatypeRestrictionFn dtv dtrelfn =
-    liftM (mapMaybe toLabels) . dtrelfn . map frLabel
+    fmap (mapMaybe toLabels) . dtrelfn . map frLabel
     where
         frLabel Nothing  = Nothing
         frLabel (Just l) = fromRDFLabel dtv l
@@ -257,7 +257,7 @@
         --  yielding an equivalent disjunction of conjunctions
         --  map concat flattens the conjunctions of conjuctions
         newgrs :: Maybe [[RDFGraph]]
-        newgrs = liftM (map concat . sequence) $ mapM newgr ris
+        newgrs = map concat . sequence <$> mapM newgr ris
 
 --  Backward apply a class restriction to single class instance (ci).
 --  Return one or more sets of antecedent results from which the consequence
@@ -527,7 +527,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012 Douglas Burke
+--    2011, 2012, 2014, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/RDF/Datatype.hs b/src/Swish/RDF/Datatype.hs
--- a/src/Swish/RDF/Datatype.hs
+++ b/src/Swish/RDF/Datatype.hs
@@ -3,7 +3,7 @@
 --------------------------------------------------------------------------------
 -- |
 --  Module      :  Datatype
---  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012 Douglas Burke
+--  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
@@ -47,7 +47,6 @@
 
 import Swish.RDF.VarBinding (RDFVarBinding, RDFOpenVarBindingModify)
 
-import Control.Monad (liftM)
 import Data.Maybe (fromMaybe, isJust, fromJust)
 
 import qualified Data.Text as T
@@ -165,7 +164,7 @@
 -- with the possibility of failure.
 toRDFLabel :: RDFDatatypeVal vt -> vt -> Maybe RDFLabel
 toRDFLabel dtv =
-    liftM (makeDatatypedLiteral dtnam) . mapV2L dtmap
+    fmap (makeDatatypedLiteral dtnam) . mapV2L dtmap
     where
         dtnam = tvalName dtv
         dtmap = tvalMap dtv
@@ -181,7 +180,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012 Douglas Burke
+--    2011, 2012, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/RDF/Datatype/XSD/Integer.hs b/src/Swish/RDF/Datatype/XSD/Integer.hs
--- a/src/Swish/RDF/Datatype/XSD/Integer.hs
+++ b/src/Swish/RDF/Datatype/XSD/Integer.hs
@@ -6,7 +6,7 @@
 --------------------------------------------------------------------------------
 -- |
 --  Module      :  Integer
---  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2014 Douglas Burke
+--  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2014, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
@@ -62,7 +62,6 @@
     , namespaceXsdType
     )
 
-import Control.Monad (liftM)
 import Data.Maybe (maybeToList)
 
 #if (!defined(__GLASGOW_HASKELL__)) || (__GLASGOW_HASKELL__ < 710)
@@ -224,7 +223,7 @@
 
 relXsdIntegerPower :: DatatypeRel Integer
 relXsdIntegerPower = mkIntRel3maybe "power" (const True)
-    [ ( const True, [ (liftM (:[]) `c2` intPower,1,2) ] )
+    [ ( const True, [ (fmap (:[]) `c2` intPower,1,2) ] )
     , ( const True, [ ] )
     , ( (>=0),      [ ] )
     ]
@@ -511,7 +510,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012 Douglas Burke
+--    2011, 2012, 2014, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/RDF/Formatter/Internal.hs b/src/Swish/RDF/Formatter/Internal.hs
--- a/src/Swish/RDF/Formatter/Internal.hs
+++ b/src/Swish/RDF/Formatter/Internal.hs
@@ -7,7 +7,7 @@
 -- |
 --  Module      :  Internal
 --  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---                 2011, 2012, 2013, 2014, 2016 Douglas Burke
+--                 2011, 2012, 2013, 2014, 2016, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
@@ -82,18 +82,12 @@
 #if (!defined(__GLASGOW_HASKELL__)) || (__GLASGOW_HASKELL__ < 710)
 import Data.Monoid (Monoid(..), mconcat)
 #endif
+import Data.Tuple (swap)
 import Data.Word
 
 import Network.URI (URI)
 import Network.URI.Ord ()
 
-#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 701)
-import Data.Tuple (swap)
-#else
-swap :: (a,b) -> (b,a)
-swap (a,b) = (b,a)
-#endif
-
 findPrefix :: URI -> M.Map a URI -> Maybe a
 findPrefix u = M.lookup u . M.fromList . map swap . M.assocs
 
@@ -709,7 +703,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012, 2013 Douglas Burke
+--    2011, 2012, 2013, 2014, 2016, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/RDF/Formatter/Turtle.hs b/src/Swish/RDF/Formatter/Turtle.hs
--- a/src/Swish/RDF/Formatter/Turtle.hs
+++ b/src/Swish/RDF/Formatter/Turtle.hs
@@ -7,7 +7,7 @@
 -- |
 --  Module      :  Turtle
 --  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---                 2011, 2012, 2013, 2014 Douglas Burke
+--                 2011, 2012, 2013, 2014, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
@@ -90,6 +90,7 @@
 
 import Swish.RDF.Vocabulary (rdfType, rdfNil)
 
+import Control.Applicative ((<$>))
 import Control.Monad (liftM)
 import Control.Monad.State (State, modify, gets, runState)
 
@@ -359,9 +360,7 @@
 formatLabel ctxt (Res sn)
   | ctxt == PredContext && sn == rdfType = return "a"
   | ctxt == ObjContext  && sn == rdfNil  = return "()"
-  | otherwise = do
-  pr <- gets prefixes
-  return $ formatScopedName sn pr
+  | otherwise = formatScopedName sn <$> gets prefixes
 
 formatLabel _ (Lit lit) = return $ formatPlainLit lit
 formatLabel _ (LangLit lit lcode) = return $ formatLangLit lit lcode
@@ -380,7 +379,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012, 2013 Douglas Burke
+--    2011, 2012, 2013, 2014, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/RDF/Graph.hs b/src/Swish/RDF/Graph.hs
--- a/src/Swish/RDF/Graph.hs
+++ b/src/Swish/RDF/Graph.hs
@@ -340,7 +340,7 @@
     getLocal   (Blank loc)  = loc
     getLocal   (Var   loc)  = '?':loc
     getLocal   (Res   sn)   = "Res_" ++ (T.unpack . getLName . getScopeLocal) sn
-    getLocal   (NoNode)     = "None"
+    getLocal   NoNode       = "None"
     getLocal   _            = "Lit_"
 
     makeLabel  ('?':loc)    = Var loc
@@ -407,9 +407,9 @@
 instance ToRDFLabel RDFLabel where
   toRDFLabel = id
   
--- | This is just @Just . id@.  
+-- | This is just @Just@.
 instance FromRDFLabel RDFLabel where
-  fromRDFLabel = Just . id
+  fromRDFLabel = Just
   
 -- TODO: remove this hack when finished conversion to Text
 maybeReadStr :: (Read a) => T.Text -> Maybe a  
@@ -1619,7 +1619,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012, 2013, 2014 Douglas Burke
+--    2011, 2012, 2013, 2014, 2015, 2016, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/RDF/Parser/N3.hs b/src/Swish/RDF/Parser/N3.hs
--- a/src/Swish/RDF/Parser/N3.hs
+++ b/src/Swish/RDF/Parser/N3.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 --------------------------------------------------------------------------------
@@ -5,12 +6,12 @@
 --------------------------------------------------------------------------------
 -- |
 --  Module      :  N3
---  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2013, 2014 Douglas Burke
+--  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2013, 2014, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  OverloadedStrings
+--  Portability :  CPP, OverloadedStrings
 --
 --  This Module implements a Notation 3 parser, returning a
 --  new 'RDFGraph' consisting of triples and namespace information parsed from
@@ -138,7 +139,12 @@
 import Control.Applicative
 import Control.Monad (forM_, foldM)
 
-import Data.Char (isSpace, isDigit, ord, isAsciiLower) 
+import Data.Char (isSpace, isDigit, ord, isAsciiLower)
+
+#if MIN_VERSION_base(4, 7, 0)
+import Data.Functor (($>))
+#endif
+
 import Data.Maybe (fromMaybe, fromJust)
 import Data.Word (Word32)
 
@@ -151,6 +157,11 @@
 import qualified Data.Text as T
 import qualified Data.Text.Lazy as L
 
+#if !MIN_VERSION_base(4, 7, 0)
+($>) :: Functor f => f a -> b -> f b
+($>) = flip (<$)
+#endif
+
 ----------------------------------------------------------------------
 -- Define parser state and helper functions
 ----------------------------------------------------------------------
@@ -547,12 +558,12 @@
 -}
 protectedChar :: N3Parser Char
 protectedChar =
-  (char 't' *> return '\t')
-  <|> (char 'n' *> return '\n')
-  <|> (char 'r' *> return '\r')
-  <|> (char '"' *> return '"')
-  <|> (char '\'' *> return '\'')
-  <|> (char '\\' *> return '\\')
+  (char 't' $> '\t')
+  <|> (char 'n' $> '\n')
+  <|> (char 'r' $> '\r')
+  <|> (char '"' $> '"')
+  <|> (char '\'' $> '\'')
+  <|> (char '\\' $> '\\')
   <|> (char 'u' *> hex4)
   <|> (char 'U' *> hex8)
 
@@ -624,14 +635,14 @@
 
 _echar' :: N3Parser Char
 _echar' = 
-  (char 't' *> pure '\t') <|>
-  (char 'b' *> pure '\b') <|>
-  (char 'n' *> pure '\n') <|>
-  (char 'r' *> pure '\r') <|>
-  (char 'f' *> pure '\f') <|>
-  (char '\\' *> pure '\\') <|>
-  (char '"' *> pure '"') <|>
-  (char '\'' *> pure '\'')
+  (char 't' $> '\t') <|>
+  (char 'b' $> '\b') <|>
+  (char 'n' $> '\n') <|>
+  (char 'r' $> '\r') <|>
+  (char 'f' $> '\f') <|>
+  (char '\\' $> '\\') <|>
+  (char '"' $> '"') <|>
+  (char '\'' $> '\'')
 
 _uchar' :: N3Parser Char
 _uchar' =
@@ -859,7 +870,7 @@
 
 existential :: N3Parser ()
 -- existential = try (atWord "forSome") *> symbolCsl >> return ()
-existential = atWord "forSome" *> symbolCsl *> pure ()
+existential = (atWord "forSome" *> symbolCsl) $> ()
 
 {-
 simpleStatement ::=		|	subject propertylist
@@ -887,8 +898,8 @@
 expression = do
   i <- pathItem
   
-  let backwardExpr = char '!' *> return addStatementRev 
-      forwardExpr  = char '^' *> return addStatement
+  let backwardExpr = char '!' $> addStatementRev
+      forwardExpr  = char '^' $> addStatement
   
   mpt <- optional
         ( (,) <$> lexeme (forwardExpr <|> backwardExpr) <*> lexeme expression )
@@ -1222,7 +1233,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012, 2013 Douglas Burke
+--    2011, 2012, 2013, 2014, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/RDF/Parser/NTriples.hs b/src/Swish/RDF/Parser/NTriples.hs
--- a/src/Swish/RDF/Parser/NTriples.hs
+++ b/src/Swish/RDF/Parser/NTriples.hs
@@ -1,15 +1,17 @@
+{-# LANGUAGE CPP #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
 
 -- |
 --  Module      :  NTriples
---  Copyright   :  (c) 2011, 2012, 2013 Douglas Burke
+--  Copyright   :  (c) 2011, 2012, 2013, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  H98
+--  Portability :  CPP
 --
 --  This Module implements a NTriples parser, returning a
 --  new 'RDFGraph' consisting of triples and namespace information parsed from
@@ -66,11 +68,21 @@
 import qualified Data.Text as T
 import qualified Data.Text.Lazy as L
 
-import Data.Char (isAsciiLower, isAsciiUpper, isDigit, ord) 
+import Data.Char (isAsciiLower, isAsciiUpper, isDigit, ord)
+
+#if MIN_VERSION_base(4, 7, 0)
+import Data.Functor (($>))
+#endif
+
 import Data.Maybe (fromMaybe)
 
 import Text.ParserCombinators.Poly.StateText
 
+#if !MIN_VERSION_base(4, 7, 0)
+($>) :: Functor f => f a -> b -> f b
+($>) = flip (<$)
+#endif
+
 ----------------------------------------------------------------------
 -- Define parser state and helper functions
 ----------------------------------------------------------------------
@@ -379,11 +391,11 @@
 
 protectedChar :: NTParser Char
 protectedChar =
-  (char 't' *> return '\t')
-  <|> (char 'n' *> return '\n')
-  <|> (char 'r' *> return '\r')
-  <|> (char '"' *> return '"')
-  <|> (char '\\' *> return '\\')
+  (char 't' $> '\t')
+  <|> (char 'n' $> '\n')
+  <|> (char 'r' $> '\r')
+  <|> (char '"' $> '"')
+  <|> (char '\\' $> '\\')
   <|> (char 'u' *> hex4)
   <|> (char 'U' *> hex8)
 
@@ -394,7 +406,7 @@
 
 --------------------------------------------------------------------------------
 --
---  Copyright (c) 2011, 2012, 2013 Douglas Burke
+--  Copyright (c) 2011, 2012, 2013, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/RDF/Parser/Turtle.hs b/src/Swish/RDF/Parser/Turtle.hs
--- a/src/Swish/RDF/Parser/Turtle.hs
+++ b/src/Swish/RDF/Parser/Turtle.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 --------------------------------------------------------------------------------
@@ -5,12 +6,12 @@
 --------------------------------------------------------------------------------
 -- |
 --  Module      :  Turtle
---  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2013, 2014 Douglas Burke
+--  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2013, 2014, 2018 Douglas Burke
 --  License     :  GPL V2
 -- 
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  OverloadedStrings
+--  Portability :  CPP, OverloadedStrings
 -- 
 --  This Module implements a Turtle parser, returning a
 --  new 'RDFGraph' consisting of triples and namespace information parsed from
@@ -104,6 +105,11 @@
 import Control.Monad (foldM)
 
 import Data.Char (chr, isAsciiLower, isAsciiUpper, isDigit, isHexDigit, ord, toLower)
+
+#if MIN_VERSION_base(4, 7, 0)
+import Data.Functor (($>))
+#endif
+
 import Data.Maybe (fromMaybe)
 import Data.Word (Word32)
 
@@ -116,6 +122,11 @@
 import qualified Data.Text as T
 import qualified Data.Text.Lazy as L
 
+#if !MIN_VERSION_base(4, 7, 0)
+($>) :: Functor f => f a -> b -> f b
+($>) = flip (<$)
+#endif
+
 ----------------------------------------------------------------------
 -- Define parser state and helper functions
 ----------------------------------------------------------------------
@@ -264,7 +275,7 @@
 
 -- this is a lot simpler than N3
 atWord :: T.Text -> TurtleParser ()
-atWord s = char '@' *> lexeme (stringT s) *> pure ()
+atWord s = (char '@' *> lexeme (stringT s)) $> ()
 
 -- | Case insensitive match.
 charI ::
@@ -751,7 +762,7 @@
 noTrailingDotM ::
   TurtleParser L.Text -- ^ This *should not* match '.'
   -> TurtleParser L.Text
-noTrailingDotM  = noTrailing (char '.' *> pure ".") (L.unpack . L.concat)
+noTrailingDotM  = noTrailing (char '.' $> ".") (L.unpack . L.concat)
 
 {-
 [144s]	LANGTAG	::=	'@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)*
@@ -937,14 +948,14 @@
 
 _echar' :: TurtleParser Char
 _echar' = 
-  (char 't' *> pure '\t') <|>
-  (char 'b' *> pure '\b') <|>
-  (char 'n' *> pure '\n') <|>
-  (char 'r' *> pure '\r') <|>
-  (char 'f' *> pure '\f') <|>
-  (char '\\' *> pure '\\') <|>
-  (char '"' *> pure '"') <|>
-  (char '\'' *> pure '\'')
+  (char 't' $> '\t') <|>
+  (char 'b' $> '\b') <|>
+  (char 'n' $> '\n') <|>
+  (char 'r' $> '\r') <|>
+  (char 'f' $> '\f') <|>
+  (char '\\' $> '\\') <|>
+  (char '"' $> '"') <|>
+  (char '\'' $> '\'')
 
 {-
 [161s]	WS	::=	#x20 | #x9 | #xD | #xA
@@ -1039,7 +1050,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012, 2013 Douglas Burke
+--    2011, 2012, 2013, 2014, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/RDF/Parser/Utils.hs b/src/Swish/RDF/Parser/Utils.hs
--- a/src/Swish/RDF/Parser/Utils.hs
+++ b/src/Swish/RDF/Parser/Utils.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 --------------------------------------------------------------------------------
@@ -5,12 +6,12 @@
 --------------------------------------------------------------------------------
 -- |
 --  Module      :  Utils
---  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2013, 2014 Douglas Burke
+--  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2013, 2014, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  OverloadedStrings
+--  Portability :  CPP, OverloadedStrings
 --
 --  Support for the RDF Parsing modules.
 --
@@ -67,6 +68,11 @@
     )
 
 import Data.Char (isSpace, isHexDigit, chr)
+
+#if MIN_VERSION_base(4, 7, 0)
+import Data.Functor (($>))
+#endif
+
 import Data.Maybe (fromMaybe, fromJust)
 
 import Network.URI (URI(..), relativeTo, parseURIReference)
@@ -78,6 +84,11 @@
 import qualified Data.Text.Lazy as L
 import qualified Data.Text.Read as R
 
+#if !MIN_VERSION_base(4, 7, 0)
+($>) :: Functor f => f a -> b -> f b
+($>) = flip (<$)
+#endif
+
 -- Code
 
 -- | Append the two URIs. Given the change in signature of
@@ -154,7 +165,7 @@
 
 -- | Run the parser and ignore the result.
 ignore :: (Applicative f) => f a -> f ()
-ignore f = f *> pure ()
+ignore f = f $> ()
 
 -- | Match the character.
 char :: Char -> Parser s Char
@@ -216,7 +227,7 @@
     -> Parser s [a]
 manyTill p end = go
   where
-    go = (end *> return [])
+    go = (end $> [])
          <|>
          ((:) <$> p <*> go)
 
@@ -265,7 +276,7 @@
 
 -- TODO: this should use eoln rather than a check on \n
 oneLineComment :: Parser s ()
-oneLineComment = ichar '#' *> manySatisfy (/= '\n') *> pure ()
+oneLineComment = (ichar '#' *> manySatisfy (/= '\n')) $> ()
 
 {-
 
@@ -344,7 +355,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012, 2014 Douglas Burke
+--    2011, 2012, 2014, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/Script.hs b/src/Swish/Script.hs
--- a/src/Swish/Script.hs
+++ b/src/Swish/Script.hs
@@ -6,7 +6,7 @@
 --------------------------------------------------------------------------------
 {- |
 Module      :  Script
-Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2014 Douglas Burke
+Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2014, 2018 Douglas Burke
 License     :  GPL V2
 
 Maintainer  :  Douglas Burke
@@ -132,6 +132,10 @@
 import Data.Monoid (Monoid(..))
 #endif
 
+#if MIN_VERSION_base(4, 7, 0)
+import Data.Functor (($>))
+#endif
+
 import Network.URI (URI(..))
 
 import qualified Control.Exception as CE
@@ -142,6 +146,11 @@
 import qualified Data.Text.Lazy.IO as LIO
 import qualified System.IO.Error as IO
 
+#if !MIN_VERSION_base(4, 7, 0)
+($>) :: Functor f => f a -> b -> f b
+($>) = flip (<$)
+#endif
+
 ------------------------------------------------------------
 --
 --  The parser used to be based on the Notation3 parser, and used many
@@ -356,7 +365,7 @@
 -- TODO: is the loss of identLetter a problem?
 commandName :: String -> N3Parser ()
 -- commandName cmd = try (string cmd *> notFollowedBy identLetter *> whiteSpace)
-commandName cmd = symbol cmd *> pure ()
+commandName cmd = symbol cmd $> ()
 
 restOfLine :: N3Parser String
 restOfLine = manyTill (satisfy (const True)) eoln <* whiteSpace
@@ -379,9 +388,7 @@
 graphExpr =
         graphOnly
     <|>
-        do  { f <- formulaExpr
-            ; return $ liftM (liftM formExpr) f
-            }
+        fmap (fmap formExpr) <$> formulaExpr
 
 graphOnly :: N3Parser (SwishStateIO (Either String RDFGraph))
 graphOnly =
@@ -452,7 +459,7 @@
 ssAddReturnFormula nam gf =
         do  { egr <- gf
             ; ssAddGraph nam [return egr]
-            ; return $ liftM (Formula nam) egr
+            ; return $ fmap (Formula nam) egr
             }
 
 ssAddGraph ::
@@ -470,7 +477,7 @@
             }
 
 ssGetGraph :: ScopedName -> SwishStateIO (Either String RDFGraph)
-ssGetGraph nam = liftM head <$> ssGetList nam
+ssGetGraph nam = fmap head <$> ssGetList nam
   
 ssGetFormula :: ScopedName -> SwishStateIO (Either String RDFFormula)
 ssGetFormula nam = gets find
@@ -880,10 +887,7 @@
         Nothing  -> fromStdin
         Just uri -> fromUri uri
     where
-    fromStdin =
-        do  { dat <- lift LIO.getContents
-            ; return $ Right dat
-            }
+    fromStdin = Right <$> lift LIO.getContents
     fromUri = fromFile
     fromFile uri | uriScheme uri == "file:" = Right `fmap` lift (LIO.readFile $ uriPath uri)
                  | otherwise = error $ "Unsupported file name for read: " ++ show uri
@@ -1482,7 +1486,7 @@
 --------------------------------------------------------------------------------
 --
 --  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
---    2011, 2012 Douglas Burke  
+--    2011, 2012, 2014, 2018 Douglas Burke
 --  All rights reserved.
 --
 --  This file is part of Swish.
diff --git a/src/Swish/VarBinding.hs b/src/Swish/VarBinding.hs
--- a/src/Swish/VarBinding.hs
+++ b/src/Swish/VarBinding.hs
@@ -123,8 +123,10 @@
 
 -- |Return a list of the variables bound by a supplied variable binding
 --
+-- The Ord instance on b is not needed (it was circa GHC 7.6) but is
+-- kept in to avoid the need to increase the minor version number.
 boundVars :: (Ord a, Ord b) => VarBinding a b -> S.Set a
-boundVars = S.map fst . vbEnum  -- Ord b is needed got GHC 7.6
+boundVars = S.map fst . vbEnum
 
 -- |VarBinding subset function, tests to see if one query binding
 --  is a subset of another;  i.e. every query variable mapping defined
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,4 +1,4 @@
 flags: {}
 packages:
 - '.'
-resolver: lts-10.8
+resolver: lts-11.1
diff --git a/swish.cabal b/swish.cabal
--- a/swish.cabal
+++ b/swish.cabal
@@ -1,7 +1,7 @@
 Name:               swish
-Version:            0.9.2.0
+Version:            0.9.2.1
 Stability:          experimental
-License:            LGPL
+License:            LGPL-2.1
 License-file:       LICENSE 
 Author:             Graham Klyne - GK@ninebynine.org
 Copyright:          (c) 2003, 2004 G. Klyne; 2009 Vasili I Galchin; 2011, 2012, 2013, 2014, 2015, 2016, 2017 Doug Burke; All rights reserved.
@@ -9,7 +9,7 @@
 Category:           Semantic Web
 Synopsis:           A semantic web toolkit. 
 
-Tested-With:        GHC==8.0.2
+Tested-With:        GHC==8.2.2
 Cabal-Version:      >= 1.9.2
 Homepage:           https://bitbucket.org/doug_burke/swish/wiki/Home
 Bug-reports:        https://bitbucket.org/doug_burke/swish/issues
@@ -90,35 +90,28 @@
 
 Library
    Build-Depends:
-      base >=3 && < 5,
-      containers >= 0.4 && < 0.6,
+      base >= 4.5 && < 4.12,
+      containers >= 0.5 && < 0.6,
+      directory >= 1.0 && < 1.4,
       filepath >= 1.1 && < 1.5,
       -- Early versions of hashable 1.2 are problematic
       hashable (>= 1.1 && < 1.2) || (>= 1.2.0.6 && <1.3),
+      intern >= 0.8 && < 1.0,
       mtl >= 2 && < 3,
       old-locale == 1.0.*, 
       polyparse >= 1.6 && <= 1.12,
       semigroups >= 0.5 && < 0.19,
       text >= 0.11 && < 1.3,
-      time >= 1.1 && < 1.9
+      -- I don't think 1.9.0 will work and it was quicly replaced
+      -- so do not support it           
+      time (>= 1.1 && < 1.9) || (>= 1.9.1 && < 1.10)
 
    if flag(network-uri)
      build-depends: network-uri == 2.6.*
-                    -- , network == 2.6.*
    else
      build-depends: network-uri < 2.6
                     , network >= 2.4 && < 2.6
 
-   if impl(ghc < 7.4.0)
-      Build-Depends:   intern == 0.8
-   if impl(ghc >= 7.4.0)
-      Build-Depends:   intern >= 0.8 && < 1.0
-
-   if impl(ghc < 7.6.0)
-      Build-Depends:   directory >= 1.0 && < 1.2
-   if impl(ghc >= 7.6.0)
-      Build-Depends:   directory >= 1.0 && < 1.4
-
    Hs-Source-Dirs: src/
    Other-Modules:  Swish.RDF.Formatter.Internal
 
@@ -279,7 +272,6 @@
 
    if flag(network-uri)
      build-depends: network-uri
-                    -- , network
    else
      build-depends: network-uri
                     , network
@@ -304,7 +296,6 @@
 
    if flag(network-uri)
      build-depends: network-uri
-                    -- , network
    else
      build-depends: network-uri
                     , network
@@ -329,7 +320,6 @@
 
    if flag(network-uri)
      build-depends: network-uri
-                    -- , network
    else
      build-depends: network-uri
                     , network
@@ -354,7 +344,6 @@
 
    if flag(network-uri)
      build-depends: network-uri
-                    -- , network
    else
      build-depends: network-uri
                     , network
@@ -381,7 +370,6 @@
 
    if flag(network-uri)
      build-depends: network-uri
-                    -- , network
    else
      build-depends: network-uri
                     , network
@@ -406,7 +394,6 @@
 
    if flag(network-uri)
      build-depends: network-uri
-                    -- , network
    else
      build-depends: network-uri
                     , network
@@ -431,7 +418,6 @@
 
    if flag(network-uri)
      build-depends: network-uri
-                    -- , network
    else
      build-depends: network-uri
                     , network
@@ -456,7 +442,6 @@
 
    if flag(network-uri)
      build-depends: network-uri
-                    -- , network
    else
      build-depends: network-uri
                     , network
@@ -481,7 +466,6 @@
 
    if flag(network-uri)
      build-depends: network-uri
-                    --, network
    else
      build-depends: network-uri
                     , network
@@ -523,7 +507,6 @@
 
    if flag(network-uri)
      build-depends: network-uri
-                    -- , network
    else
      build-depends: network-uri
                     , network
@@ -587,7 +570,6 @@
 
      if flag(network-uri)
        build-depends: network-uri
-                      --, network
      else
        build-depends: network-uri
                       , network
diff --git a/tests/RDFGraphTest.hs b/tests/RDFGraphTest.hs
--- a/tests/RDFGraphTest.hs
+++ b/tests/RDFGraphTest.hs
@@ -74,7 +74,10 @@
 
 import Network.URI (URI, parseURI)
 
-#if MIN_VERSION_time(1,5,0)
+#if MIN_VERSION_time(1,9,0)
+import Data.Time (UTCTime(..), Day, fromGregorian, defaultTimeLocale)
+import Data.Time.Format.Internal (buildTime)
+#elif MIN_VERSION_time(1,5,0)
 import Data.Time (UTCTime(..), Day, fromGregorian, buildTime, defaultTimeLocale)
 #else
 import Data.Time (UTCTime(..), Day, fromGregorian, buildTime)
diff --git a/tests/RDFQueryTest.hs b/tests/RDFQueryTest.hs
--- a/tests/RDFQueryTest.hs
+++ b/tests/RDFQueryTest.hs
@@ -6,7 +6,7 @@
 --------------------------------------------------------------------------------
 -- |
 --  Module      :  RDFQueryTest
---  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2013, 2014 Douglas Burke
+--  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2013, 2014, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
@@ -1051,24 +1051,24 @@
   [ test "testQuery41" (not $ null var41)
   , testEq "testQuery41a" 1 (length var41)
   , testEq "testResult41" 1 (length res41)
-  , testGr "testResult41a" result41a (fst $ unzip $ head res41)
+  , testGr "testResult41a" result41a (map fst (head res41))
   , testEqv "testUnbound41a" [] (snd $ head $ head res41)
   , test "testQuery42" (not $ null var42)
   , testEq "testQuery42a" 1 (length var42)
   , testEq "testResult42" 1 (length res42)
-  , testGr "testResult42a" result42a (fst $ unzip $ head res42)
+  , testGr "testResult42a" result42a (map fst (head res42))
   , testEqv "testUnbound42a" [Var "b"] (snd $ head $ head res42)
   , test "testQuery43" (not $ null var43)
   , testEq "testQuery43a" 1 (length var43)
   , testEq "testResult43" 1 (length res43)
-  , testGr "testResult43a" result43a (fst $ unzip $ head res43)
+  , testGr "testResult43a" result43a (map fst (head res43))
   , testEqv "testUnbound43a" [Var "a"] (snd $ head $ head res43)
   , test "testQuery44" (not $ null var44)
   , testEq "testQuery44a"   2 (length var44)
   , testEq "testResult44"   2 (length res44)
-  , testGr "testResult44a"  result44a  (fst $ unzip res44_2)
+  , testGr "testResult44a"  result44a  (map fst res44_2)
   , testEqv "testUnbound44a" unbound44a (snd $ head res44_2)
-  , testGr "testResult44b"  result44b  (fst $ unzip res44_1)
+  , testGr "testResult44b"  result44b  (map fst res44_1)
   , testEqv "testUnbound44b" unbound44b (snd $ head res44_1)
   , test "testQuery45" (not $ null var45)
   , testEq "testQuery45a"   1 (length var45)
diff --git a/tests/TestHelpers.hs b/tests/TestHelpers.hs
--- a/tests/TestHelpers.hs
+++ b/tests/TestHelpers.hs
@@ -3,7 +3,7 @@
 --------------------------------------------------------------------------------
 -- |
 --  Module      :  TestHelpers
---  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011 Douglas Burke
+--  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2018 Douglas Burke
 --  License     :  GPL V2
 --
 --  Maintainer  :  Douglas Burke
@@ -122,7 +122,7 @@
 
 -- Compare lists and lists of lists and Maybe lists for set equivalence:
 
-data MaybeListTest a = MaybeListTest (Maybe (S.Set a))
+newtype MaybeListTest a = MaybeListTest (Maybe (S.Set a))
 
 instance (Ord a) => Eq (MaybeListTest a) where
     MaybeListTest (Just a1) == MaybeListTest (Just a2) = a1 == a2
diff --git a/tests/TurtleTest.hs b/tests/TurtleTest.hs
--- a/tests/TurtleTest.hs
+++ b/tests/TurtleTest.hs
@@ -5,7 +5,7 @@
 --------------------------------------------------------------------------------
 -- |
 --  Module      :  TurtleTest
---  Copyright   :  (c) 2013 Douglas Burke
+--  Copyright   :  (c) 2013, 2018 Douglas Burke
 --  License     :  GPL V2
 -- 
 --  Maintainer  :  Douglas Burke
@@ -374,7 +374,7 @@
      ]
 
 {-
-### Failure in: 0:6:1:"example: 2.7 a"
+--- Failure in: 0:6:1:"example: 2.7 a"
 expected: Graph, formulae:
 arcs:
     (_:23,foaf:name,"Bob")
