diff --git a/Util/Binary.hs b/Util/Binary.hs
--- a/Util/Binary.hs
+++ b/Util/Binary.hs
@@ -2,21 +2,21 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FlexibleContexts #-}
 
--- | Library for converting types to and from binary, so that they can
--- be written to and from files, stored compactly in memory, and so on.
---
--- This is a preliminary version of the library, hence I have decided
--- /not/ to optimise heavily, beyond putting in strictness annotations
--- in where they seem appropriate.
---
--- A good place to start optimising would probably be the separate
--- "Bytes" libary.
---
--- See also "BinaryInstances", which declares instances for the standard
--- types (and one or two others), "BinaryUtils", which contains
--- (mostly) material for declaring new instances, "BinaryExtras",
--- which contains other miscellaneous utilities, and finally
--- "BinaryAll" which just imports and reexports everything.
+{- | Library for converting types to and from binary, so that they can
+be written to and from files, stored compactly in memory, and so on.
+
+This is a preliminary version of the library, hence I have decided
+/not/ to optimise heavily, beyond putting in strictness annotations
+in where they seem appropriate.
+
+A good place to start optimising would probably be the separate
+"Bytes" libary.
+
+See also "BinaryInstances", which declares instances for the standard
+types (and one or two others), "BinaryUtils", which contains
+(mostly) material for declaring new instances, "BinaryExtras",
+which contains other miscellaneous utilities, and finally
+"BinaryAll" which just imports and reexports everything. -}
 module Util.Binary (
 
    hWrite, -- :: HasBinary a IO => Handle -> a -> IO ()
@@ -27,12 +27,12 @@
    readFromBytes, -- :: HasBinary a StateBinArea => (Bytes,Int) -> IO a
 
 
-   HasBinary(..),
-   WriteBinary(..),
-   ReadBinary(..),
+   HasBinary (..),
+   WriteBinary (..),
+   ReadBinary (..),
 
-   -- Ways of constructing WriteBinary/ReadBinary instances (not usually
-   -- required explicitly).
+   {- Ways of constructing WriteBinary/ReadBinary instances (not usually
+   required explicitly). -}
    toWriteBinaryHandle, -- :: Handle -> WriteBinary IO
    toReadBinaryHandle, -- :: Handle -> ReadBinary IO
 
@@ -43,19 +43,19 @@
    -- writing a BinArea
 
    -- create
-   mkEmptyBinArea, -- :: Int -> IO BinArea
-   -- pass as argument to writeBin
-   writeBinaryBinArea, -- :: WriteBinary StateBinArea
-   -- close and get contents.
+   mkEmptyBinArea, {- :: Int -> IO BinArea
+   pass as argument to writeBin -}
+   writeBinaryBinArea, {- :: WriteBinary StateBinArea
+   close and get contents. -}
    closeBinArea, -- :: BinArea -> IO (Bytes,Int)
 
    -- reading a BinArea
 
    -- create
-   mkBinArea, -- :: (Bytes,Int) -> BinArea
-   -- pass to things which read.
-   readBinaryBinArea, -- :: ReadBinary StateBinArea
-   -- check that the BinArea is completely read.
+   mkBinArea, {- :: (Bytes,Int) -> BinArea
+   pass to things which read. -}
+   readBinaryBinArea, {- :: ReadBinary StateBinArea
+   check that the BinArea is completely read. -}
    checkFullBinArea, -- :: BinArea -> IO ()
 
 
@@ -76,20 +76,20 @@
 -- Our imports
 import Util.Bytes
 
--- ----------------------------------------------------------------------
--- The general framework
--- Type variable "m" is a monad; "a" is the thing to read or write.
---
--- NB.  Bytes values are currently not subject to the garbage-collector,
--- and so need to be explicitly freed.   The following rules for this
--- should be observed.
---
--- (1) For writeBytes, it is only guaranteed that the argument "Bytes"
---     will be valid at the actual time of evaluation.
--- (2) For readBytes, it is the caller's responsibility to free the returned
---     area.
--- ----------------------------------------------------------------------
+{- ----------------------------------------------------------------------
+The general framework
+Type variable "m" is a monad; "a" is the thing to read or write.
 
+NB.  Bytes values are currently not subject to the garbage-collector,
+and so need to be explicitly freed.   The following rules for this
+should be observed.
+
+(1) For writeBytes, it is only guaranteed that the argument "Bytes"
+will be valid at the actual time of evaluation.
+(2) For readBytes, it is the caller's responsibility to free the returned
+area.
+---------------------------------------------------------------------- -}
+
 -- | A consumer of binary data
 data WriteBinary m =
    WriteBinary {
@@ -114,13 +114,13 @@
    readBin :: ReadBinary m -> m a
       -- ^ Given a source of binary data, provide an (a)
 
--- ----------------------------------------------------------------------
--- Reading/Writing HasBinary instances to Handles.
--- ----------------------------------------------------------------------
+{- ----------------------------------------------------------------------
+Reading/Writing HasBinary instances to Handles.
+---------------------------------------------------------------------- -}
 
 -- | Write an (a) to a 'Handle'
 hWrite :: HasBinary a IO => Handle -> a -> IO ()
-hWrite handle a = writeBin (toWriteBinaryHandle handle) a
+hWrite handle = writeBin $ toWriteBinaryHandle handle
 
 
 -- | Read an (a) from a 'Handle'
@@ -141,36 +141,12 @@
       readBytes = hGetBytes handle
       }
 
-toWriteBinaryHandleDebug :: Handle -> WriteBinary IO
-toWriteBinaryHandleDebug handle =
-   WriteBinary {
-      writeByte = (\ b -> bracketDebug 1 (hPutByte handle b)),
-      writeBytes = (\ b i -> bracketDebug i (hPutBytes handle b i))
-      }
-
-toReadBinaryHandleDebug :: Handle -> ReadBinary IO
-toReadBinaryHandleDebug handle =
-   ReadBinary {
-      readByte = bracketDebug 1 (hGetByte handle),
-      readBytes = (\ i -> bracketDebug i (hGetBytes handle i))
-      }
-
-bracketDebug :: Int -> IO a -> IO a
-bracketDebug i act =
-   do
-      putStr ("[" ++ show i)
-      hFlush stdout
-      a <- act
-      putStr "]"
-      hFlush stdout
-      return a
+{- ----------------------------------------------------------------------
+Writing HasBinary instances to a memory area
 
--- ----------------------------------------------------------------------
--- Writing HasBinary instances to a memory area
---
--- We do this by allocating an area, and then doubling its size as
--- necessary.
--- ----------------------------------------------------------------------
+We do this by allocating an area, and then doubling its size as
+necessary.
+---------------------------------------------------------------------- -}
 
 -- | Somewhere to where you write binary data in memory.
 data BinArea = BinArea {
@@ -180,47 +156,46 @@
    }
 
 -- | Write an (a) to memory.  The 'Int' is the length of the area.
-writeToBytes :: HasBinary a StateBinArea => a -> IO (Bytes,Int)
+writeToBytes :: HasBinary a StateBinArea => a -> IO (Bytes, Int)
 writeToBytes = writeToBytes0 1000
-   -- Be generous, since memory is cheap.  Make it a bit less than a power
-   -- of two, since some memory allocation algorithms (buddy algorithm)
-   -- like this.
+   {- Be generous, since memory is cheap.  Make it a bit less than a power
+   of two, since some memory allocation algorithms (buddy algorithm)
+   like this. -}
 
--- | Write an (a) to memory.
--- The integer argument is an initial guess at the number of bytes
--- that will be needed.  This should be greater than 0.  If it is
--- too small, there will be unnecessary reallocations; if too large,
--- too much memory will be used.
-writeToBytes0 :: HasBinary a StateBinArea => Int -> a -> IO (Bytes,Int)
---
+{- | Write an (a) to memory.
+The integer argument is an initial guess at the number of bytes
+that will be needed.  This should be greater than 0.  If it is
+too small, there will be unnecessary reallocations; if too large,
+too much memory will be used. -}
+writeToBytes0 :: HasBinary a StateBinArea => Int -> a -> IO (Bytes, Int)
 -- The result is returned as a pair (data area,length)
 writeToBytes0 len0 a =
    do
       binArea0 <- mkEmptyBinArea len0
-      ((),binArea1) <- runStateT (writeBin writeBinaryBinArea a) binArea0
+      ((), binArea1) <- runStateT (writeBin writeBinaryBinArea a) binArea0
       closeBinArea binArea1
 
 -- | Create an empty 'BinArea', given the initial size.
 mkEmptyBinArea :: Int -> IO BinArea
 -- the argument gives the initial size to use (which had better be positive).
-mkEmptyBinArea len =
+mkEmptyBinArea l =
    do
-      bytes <- bytesMalloc len
-      return (BinArea {
-         bytes = bytes,
-         len = len,
+      bs <- bytesMalloc l
+      return BinArea {
+         bytes = bs,
+         len = l,
          next = 0
-         })
+         }
 
 -- | Return all the data currently in the 'BinArea'
-closeBinArea :: BinArea -> IO (Bytes,Int)
+closeBinArea :: BinArea -> IO (Bytes, Int)
 closeBinArea binArea =
    do
       let
          bytes1 = bytes binArea
-         len = next binArea
-      bytes2 <- bytesReAlloc bytes1 len
-      return (bytes2,len)
+         l = next binArea
+      bytes2 <- bytesReAlloc bytes1 l
+      return (bytes2, l)
 
 -- | a state monad containing the BinArea.
 type StateBinArea = StateT BinArea IO
@@ -228,31 +203,26 @@
 -- | A 'BinArea' as somewhere to put binary data.
 writeBinaryBinArea :: WriteBinary StateBinArea
 writeBinaryBinArea = WriteBinary {
-   writeByte = (\ byte ->
-      StateT (\ binArea0 ->
+   writeByte = \ byte ->
+      StateT $ \ binArea0 ->
          do
             let
                next0 = next binArea0
                next1 = next0 + 1
             binArea1 <- ensureBinArea binArea0 next1
             putByteToBytes byte (bytes binArea1) next0
-            return ((),binArea1 {next = next1})
-         )
-      ),
-   writeBytes = (\ bytes' len ->
-      StateT (\ binArea0 ->
+            return ((), binArea1 {next = next1})
+   , writeBytes = \ bytes' l ->
+      StateT $ \ binArea0 ->
          do
             let
                next0 = next binArea0
-               next1 = next0 + len
+               next1 = next0 + l
             binArea1 <- ensureBinArea binArea0 next1
-            putBytesToBytes bytes' 0 (bytes binArea1) next0 len
-            return ((),binArea1 {next = next1})
-         )
-      )
+            putBytesToBytes bytes' 0 (bytes binArea1) next0 l
+            return ((), binArea1 {next = next1})
    }
 
-
 -- | ensure that the given BinArea can hold at least len bytes.
 ensureBinArea :: BinArea -> Int -> IO BinArea
 ensureBinArea binArea size =
@@ -262,36 +232,36 @@
       else
         do
            let
-              len1 = 2*size
+              len1 = 2 * size
            bytes1 <- bytesReAlloc (bytes binArea) len1
-           return (BinArea {
+           return BinArea {
               bytes = bytes1,
               len = len1,
               next = next binArea
-              })
+              }
 
--- ----------------------------------------------------------------------
--- Reading Binary instances from a memory area
--- We use BinArea's for this too.  But this is simpler, because we don't have to
--- worry about reallocing.
--- ----------------------------------------------------------------------
+{- ----------------------------------------------------------------------
+Reading Binary instances from a memory area
+We use BinArea's for this too.  But this is simpler, because we don't have to
+worry about reallocing.
+---------------------------------------------------------------------- -}
 
--- | Read a value from binary data in memory.  The 'Int' is the length,
--- and there will be an error if this is either too small or too large.
-readFromBytes :: HasBinary a StateBinArea => (Bytes,Int) -> IO a
-readFromBytes (bl@(bytes',len')) =
+{- | Read a value from binary data in memory.  The 'Int' is the length,
+and there will be an error if this is either too small or too large. -}
+readFromBytes :: HasBinary a StateBinArea => (Bytes, Int) -> IO a
+readFromBytes bl =
    do
       let
          binArea0 = mkBinArea bl
 
-      (a,binArea1) <- runStateT (readBin readBinaryBinArea) binArea0
+      (a, binArea1) <- runStateT (readBin readBinaryBinArea) binArea0
       checkFullBinArea binArea1
       return a
 
--- | Turn binary data in memory into a 'BinArea' (so that you can
--- read from it).
-mkBinArea :: (Bytes,Int) -> BinArea
-mkBinArea (bytes',len') =
+{- | Turn binary data in memory into a 'BinArea' (so that you can
+read from it). -}
+mkBinArea :: (Bytes, Int) -> BinArea
+mkBinArea (bytes', len') =
    BinArea {
       bytes = bytes',
       len = len',
@@ -300,67 +270,57 @@
 
 checkFullBinArea :: BinArea -> IO ()
 checkFullBinArea binArea =
-   if next binArea == len binArea
-      then
-         return ()
-      else
+   unless (next binArea == len binArea) $
          error "Binary.checkFullBinArea: mysterious extra bytes"
 
 
 -- | A BinArea as a source of binary data.
 readBinaryBinArea :: ReadBinary StateBinArea
 readBinaryBinArea = ReadBinary {
-   readByte = StateT (\ binArea0 ->
+   readByte = StateT $ \ binArea0 ->
       do
          let
             next0 = next binArea0
             next1 = next0 + 1
          checkBinArea binArea0 next1
          byte <- getByteFromBytes (bytes binArea0) next0
-         return (byte,binArea0 {next = next1})
-      ),
-   readBytes = (\ len ->
-      StateT (\ binArea0 ->
+         return (byte, binArea0 {next = next1})
+   , readBytes = \ l ->
+      StateT $ \ binArea0 ->
          do
             let
                next0 = next binArea0
-               next1 = next0 + len
+               next1 = next0 + l
             checkBinArea binArea0 next1
-            bytes' <- bytesMalloc len
-            putBytesToBytes (bytes binArea0) next0 bytes' 0 len
-            return (bytes',binArea0 {next = next1})
-         )
-      )
+            bytes' <- bytesMalloc l
+            putBytesToBytes (bytes binArea0) next0 bytes' 0 l
+            return (bytes', binArea0 {next = next1})
    }
 
 checkBinArea :: BinArea -> Int -> IO ()
 -- check that the given BinArea can hold at least len bytes.
 checkBinArea binArea newNext =
-   if newNext > len binArea
-      then
+   when (newNext > len binArea) $
          error "Binary.checkBinArea - BinArea overflow on read"
-      else
-         return ()
 
--- ----------------------------------------------------------------------
--- Lifting writeBinary and readBinary instances.
--- ----------------------------------------------------------------------
+{- ----------------------------------------------------------------------
+Lifting writeBinary and readBinary instances.
+---------------------------------------------------------------------- -}
 
 -- | Transform the monad used by a 'WriteBinary'
 liftWriteBinary :: (forall a . m a -> n a) -> WriteBinary m -> WriteBinary n
-liftWriteBinary lift wb =
+liftWriteBinary lft wb =
    let
-      writeByte2 b = lift (writeByte wb b)
-      writeBytes2 b i = lift (writeBytes wb b i)
+      writeByte2 b = lft (writeByte wb b)
+      writeBytes2 b i = lft (writeBytes wb b i)
    in
-      WriteBinary {writeByte = writeByte2,writeBytes = writeBytes2}
+      WriteBinary {writeByte = writeByte2, writeBytes = writeBytes2}
 
 -- | Transform the monad used by a 'ReadBinary'
 liftReadBinary :: (forall a . m a -> n a) -> ReadBinary m -> ReadBinary n
-liftReadBinary lift rb =
+liftReadBinary lft rb =
    let
-      readByte2 = lift (readByte rb)
-      readBytes2 i = lift (readBytes rb i)
+      readByte2 = lft (readByte rb)
+      readBytes2 i = lft (readBytes rb i)
    in
-      ReadBinary {readByte = readByte2,readBytes = readBytes2}
-
+      ReadBinary {readByte = readByte2, readBytes = readBytes2}
diff --git a/Util/BinaryUtils.hs b/Util/BinaryUtils.hs
--- a/Util/BinaryUtils.hs
+++ b/Util/BinaryUtils.hs
@@ -68,6 +68,7 @@
 import System.IO(Handle)
 
 -- GHC imports
+import Control.Applicative
 import Control.Monad.Trans
 
 -- our imports
@@ -142,6 +143,14 @@
          fn2 arg = fmap mapFn (fn arg)
       in
          ArgMonad fn2
+
+instance Applicative m => Applicative (ArgMonad arg m) where
+   pure v = ArgMonad (const (pure v))
+   ArgMonad fn1 <*> ArgMonad fn2 =
+      let
+         fn arg = fn1 arg <*> fn2 arg
+      in
+         ArgMonad fn
 
 instance Monad m => Monad (ArgMonad arg m) where
    (>>=) (ArgMonad fn1) getArgMonad =
diff --git a/Util/Computation.hs b/Util/Computation.hs
--- a/Util/Computation.hs
+++ b/Util/Computation.hs
@@ -105,6 +105,7 @@
         )
 where
 
+import Control.Applicative
 import Control.Monad
 
 import Control.Exception
@@ -301,6 +302,10 @@
       Value a -> Value (aToB a)
       Error e -> Error e
 
+instance Applicative WithError where
+   pure = return
+   (<*>) = ap
+
 instance Monad WithError where
    return v = hasValue v
    (>>=) aWE toBWe =
@@ -309,6 +314,13 @@
 
 newtype MonadWithError m a = MonadWithError (m (WithError a))
 
+instance Monad m => Functor (MonadWithError m) where
+   fmap f (MonadWithError a) = MonadWithError $ liftM (fmap f) a
+
+instance Monad m => Applicative (MonadWithError m) where
+   pure = return
+   (<*>) = ap
+
 instance Monad m => Monad (MonadWithError m) where
    return v = MonadWithError (return (Value v))
    (>>=) (MonadWithError act1) getAct2 =
@@ -400,4 +412,3 @@
 
 infixr 0 $$
 -- This makes $$ have fixity like $.
-
diff --git a/Util/Dynamics.hs b/Util/Dynamics.hs
--- a/Util/Dynamics.hs
+++ b/Util/Dynamics.hs
@@ -20,20 +20,7 @@
         typeMismatch,
         dynCast, -- Cast to another value of the same type, or
            -- error (useful for extracting from existential types).
-        dynCastOpt,
-
-        mkTypeRep,
-           -- :: String -> String -> TypeRep
-
-        -- Flavours of Typeable we need not already in Data.Typeable.
-        -- The only customer for these at the moment seems to be
-        -- types/DisplayView.hs
-        Typeable1_1(..),
-        Typeable2_11(..),
-        Typeable3_111(..),
-        Typeable4_0111(..),
-        Typeable5_00111(..),
-        Typeable6_000111(..),
+        dynCastOpt
         )
 where
 
@@ -89,90 +76,3 @@
 
 dynCastOpt :: (Typeable a,Typeable b) => a -> Maybe b
 dynCastOpt = Data.Dynamic.cast
-
--- | Construct a TypeRep for a type or type constructor with no arguments.
--- The first string should be the module name, the second that of the type.
-mkTypeRep :: String -> String -> TypeRep
-mkTypeRep s1 s2 = mkTyConApp (mkTyCon (s1 ++ "." ++ s2)) []
-
--- ------------------------------------------------------------
--- Flavours of Typeable we need not already in Data.Typeable.
--- The only customer for these at the moment seems to be
--- types/DisplayView.hs
--- ------------------------------------------------------------
-
-class Typeable1_1 ty where
-   typeOf1_1 :: Typeable1 typeArg => ty typeArg -> TypeRep
-
-instance (Typeable1_1 ty,Typeable1 typeArg) => Typeable (ty typeArg) where
-   typeOf (x :: ty typeArg) = (typeOf1_1 x) `mkAppTy` typeOf v
-      where
-         v :: typeArg ()
-         v = error "Dynamics.31"
-
-class Typeable2_11 ty where
-   typeOf2_11 :: (Typeable1 typeArg1,Typeable1 typeArg2)
-      => ty typeArg1 typeArg2 -> TypeRep
-
-instance (Typeable2_11 ty,Typeable1 typeArg1)
-      => Typeable1_1 (ty typeArg1) where
-   typeOf1_1 (x :: ty typeArg1 typeArg2) =
-         (typeOf2_11 x) `mkAppTy` (typeOf1 v)
-      where
-         v :: typeArg1 ()
-         v = error "Dynamics.23"
-
-class Typeable3_111 ty where
-   typeOf3_111 :: (Typeable1 typeArg1,Typeable1 typeArg2,Typeable1 typeArg3)
-      => ty typeArg1 typeArg2 typeArg3 -> TypeRep
-
-instance (Typeable3_111 ty,Typeable1 typeArg1)
-      => Typeable2_11 (ty typeArg1) where
-   typeOf2_11 (x :: ty typeArg1 typeArg2 typeArg3) =
-         (typeOf3_111 x) `mkAppTy` (typeOf1 v)
-      where
-         v :: typeArg1 ()
-         v = error "Dynamics.23"
-
-class Typeable4_0111 ty where
-   typeOf4_0111
-      :: (Typeable ty1,
-         Typeable1 typeArg1,Typeable1 typeArg2,Typeable1 typeArg3)
-      => ty ty1 typeArg1 typeArg2 typeArg3  -> TypeRep
-
-instance (Typeable4_0111 ty,Typeable ty1)
-      => Typeable3_111 (ty ty1) where
-   typeOf3_111 (x :: ty ty1 typeArg2 typeArg3 typeArg4) =
-         (typeOf4_0111 x) `mkAppTy` (typeOf v)
-      where
-         v :: ty1
-         v = error "Dynamics.23"
-
-class Typeable5_00111 ty where
-   typeOf5_00111
-      :: (Typeable ty1,Typeable ty2,
-         Typeable1 typeArg1,Typeable1 typeArg2,Typeable1 typeArg3)
-      => ty ty1 ty2 typeArg1 typeArg2 typeArg3  -> TypeRep
-
-instance (Typeable5_00111 ty,Typeable ty1)
-      => Typeable4_0111 (ty ty1) where
-   typeOf4_0111 (x :: ty ty1 ty2 typeArg1 typeArg2 typeArg3) =
-         (typeOf5_00111 x) `mkAppTy` (typeOf v)
-      where
-         v :: ty1
-         v = error "Dynamics.23"
-
-class Typeable6_000111 ty where
-   typeOf6_000111
-      :: (Typeable ty1,Typeable ty2,Typeable ty3,
-         Typeable1 typeArg1,Typeable1 typeArg2,Typeable1 typeArg3)
-      => ty ty1 ty2 ty3 typeArg1 typeArg2 typeArg3  -> TypeRep
-
-instance (Typeable6_000111 ty,Typeable ty1)
-      => Typeable5_00111 (ty ty1) where
-   typeOf5_00111 (x :: ty ty1 ty2 ty3 typeArg1 typeArg2 typeArg3) =
-         (typeOf6_000111 x) `mkAppTy` (typeOf v)
-      where
-         v :: ty1
-         v = error "Dynamics.23"
-
diff --git a/Util/ICStringLen.hs b/Util/ICStringLen.hs
--- a/Util/ICStringLen.hs
+++ b/Util/ICStringLen.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE CPP #-}
 
 -- | This module provides immutable CStrings, which additionally have
 -- the property that they are automatically freed when the garbage-collector
@@ -43,6 +44,9 @@
 import System.IO.Unsafe
 import Foreign.C.String
 import Foreign.ForeignPtr
+#if __GLASGOW_HASKELL__ > 706
+import Foreign.ForeignPtr.Unsafe
+#endif
 import Foreign.Marshal.Array
 import Foreign.Marshal.Alloc
 import Foreign.C.Types
@@ -205,4 +209,3 @@
    do
       bl <- writeToBytes a
       bytesToICStringLen bl
-
diff --git a/Util/Sources.hs b/Util/Sources.hs
--- a/Util/Sources.hs
+++ b/Util/Sources.hs
@@ -160,7 +160,9 @@
 
 import Data.Maybe
 
+import Control.Applicative
 import Control.Concurrent
+import Control.Monad
 import Data.IORef
 
 import Util.ExtendedPrelude(HasMapIO(..))
@@ -706,6 +708,10 @@
       source2 = seqSourceIO source1 getSource
    in
       SimpleSource source2
+
+instance Applicative SimpleSource where
+   pure = return
+   (<*>) = ap
 
 instance Monad SimpleSource where
    return x = SimpleSource (staticSource x)
diff --git a/Util/Thread.hs b/Util/Thread.hs
--- a/Util/Thread.hs
+++ b/Util/Thread.hs
@@ -9,8 +9,6 @@
 
    ThreadId,
 
-   hashThreadId, -- :: ThreadId -> Int32
-
    -- thread creation
 
    forkIODebug, -- :: IO () -> IO ThreadId
@@ -58,7 +56,6 @@
 import Control.Exception
 import Control.Concurrent
 import Control.Monad
-import Data.HashTable
 import Data.Int
 
 import Util.Computation
@@ -217,15 +214,3 @@
 
 mapMConcurrent_ :: (a -> IO ()) -> [a] -> IO ()
 mapMConcurrent_ mapFn as = mapM_ (\ a -> forkIO (mapFn a)) as
-
-
--- --------------------------------------------------------------------------
--- hashThreadId
--- --------------------------------------------------------------------------
-
-hashThreadId :: ThreadId -> Int32
--- Currently implemented by a horrible hack requiring access to GHC internals.
-hashThreadId (GHC.Conc.ThreadId ti) = hashInt (getThreadId ti)
-
-foreign import ccall unsafe "rts_getThreadId" getThreadId
-   :: GHC.Base.ThreadId# -> Int
diff --git a/Util/ThreadDict.hs b/Util/ThreadDict.hs
--- a/Util/ThreadDict.hs
+++ b/Util/ThreadDict.hs
@@ -7,46 +7,45 @@
    modifyThreadDict, -- :: ThreadDict a -> (Maybe a -> IO (Maybe a,b)) -> IO b
    ) where
 
-import Data.HashTable
 import Control.Concurrent
 
-import Util.Thread
+import qualified Data.Map as Map
+import Data.IORef
 
 -- -------------------------------------------------------------------------
 -- Data types
 -- -------------------------------------------------------------------------
 
-newtype ThreadDict a = ThreadDict (HashTable ThreadId a)
+newtype ThreadDict a = ThreadDict (IORef (Map.Map ThreadId a))
 
 -- -------------------------------------------------------------------------
 -- Functions
 -- -------------------------------------------------------------------------
 
 newThreadDict :: IO (ThreadDict a)
-newThreadDict =
-   do
-      table <- new (==) hashThreadId
-      return (ThreadDict table)
+newThreadDict = do
+  m <- newIORef Map.empty
+  return (ThreadDict m)
 
 writeThreadDict :: ThreadDict a -> a -> IO ()
 writeThreadDict (ThreadDict table) a =
    do
       ti <- myThreadId
-      insert table ti a
+      atomicModifyIORef table $ \ m -> (Map.insert ti a m, ())
 
 readThreadDict :: ThreadDict a -> IO (Maybe a)
 readThreadDict (ThreadDict table) =
    do
       ti <- myThreadId
-      Data.HashTable.lookup table ti
+      m <- readIORef table
+      return $ Map.lookup ti m
 
-modifyThreadDict :: ThreadDict a -> (Maybe a -> IO (Maybe a,b)) -> IO b
+modifyThreadDict :: ThreadDict a -> (Maybe a -> IO (Maybe a, b)) -> IO b
 modifyThreadDict (ThreadDict table) updateFn =
    do
       ti <- myThreadId
-      aOpt0 <- Data.HashTable.lookup table ti
-      (aOpt1,b) <- updateFn aOpt0
-      case aOpt1 of
-         Nothing -> delete table ti
-         Just a -> insert table ti a
-      return b
+      m <- readIORef table
+      (aOpt1, b) <- updateFn $ Map.lookup ti m
+      atomicModifyIORef table $ \ im -> ((case aOpt1 of
+            Nothing -> Map.delete ti
+            Just a -> Map.insert ti a) im, b)
diff --git a/uni-util.cabal b/uni-util.cabal
--- a/uni-util.cabal
+++ b/uni-util.cabal
@@ -1,5 +1,5 @@
 name:           uni-util
-version:        2.2.1.2
+version:        2.3.0.0
 build-type:     Simple
 license:        LGPL
 license-file:   LICENSE
@@ -23,6 +23,10 @@
   description: add debug traces
   default: False
 
+flag parsec1
+    Description: Use parsec1
+    Default: True
+
 library
  exposed-modules:
   Util.Huffman, Util.CompileFlags, Util.Queue,
@@ -44,16 +48,19 @@
  include-dirs: include
  c-sources: new_object.c, default_options.c
 
- build-depends: base >= 4 && < 5, parsec < 3.2, mtl, directory,
+ build-depends: base >= 4 && < 5, mtl, directory,
   network, containers, bytestring, array, old-time
 
  if flag(base4)
    build-depends: ghc-prim
 
+ if flag(parsec1)
+   build-depends: parsec1
+ else
+   build-depends: parsec
+
  if flag(debug)
    cpp-options: -DDEBUG
 
  if os(windows)
    cpp-options: -DWINDOWS
-
- ghc-options: -fwarn-unused-imports -fno-warn-warnings-deprecations
