diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,7 @@
 # mixed-types-num change log
 
+* v 0.4.0 2019-04-10
+  * eliminated dependency on convertible, improving ghcjs compatibility
 * v 0.3.2 2019-01-08
   * added divI and mod
   * added enforceRange
diff --git a/mixed-types-num.cabal b/mixed-types-num.cabal
--- a/mixed-types-num.cabal
+++ b/mixed-types-num.cabal
@@ -1,11 +1,11 @@
 name:           mixed-types-num
-version:        0.3.2
+version:        0.4.0
 cabal-version:  >= 1.9.2
 build-type:     Simple
 homepage:       https://github.com/michalkonecny/mixed-types-num
 author:         Michal Konecny
 maintainer:     Michal Konecny <mikkonecny@gmail.com>
-copyright:      (c) 2015-2018 Michal Konecny
+copyright:      (c) 2015-2019 Michal Konecny
 license:        BSD3
 license-file:   LICENSE
 extra-source-files:  changelog.md
@@ -42,8 +42,9 @@
   hs-source-dirs:  src
   build-depends:
     base >= 4.8 && < 5
-    , convertible >= 1.1.1.0
+    -- , convertible >= 1.1.1.0
     , template-haskell
+    , mtl
     , hspec >= 2.1
     , hspec-smallcheck >= 0.3
     , smallcheck == 1.1.*
@@ -64,6 +65,9 @@
   exposed-modules:
     Utils.TH.DeclForTypes
     Utils.Test.EnforceRange
+    Data.Convertible.Base
+    Data.Convertible.Utils
+    Data.Convertible.Instances.Num
     Control.CollectErrors
     Numeric.CollectErrors
     Numeric.MixedTypes.PreludeHiding
@@ -105,7 +109,7 @@
     Numeric.MixedTypes.RingSpec
     Numeric.MixedTypes.RoundSpec
   build-depends:
-    base >= 4.8
+    base >= 4.8 && < 5
     , mixed-types-num
     , hspec >= 2.1
     , hspec-smallcheck >= 0.3
diff --git a/src/Control/CollectErrors.hs b/src/Control/CollectErrors.hs
--- a/src/Control/CollectErrors.hs
+++ b/src/Control/CollectErrors.hs
@@ -30,7 +30,8 @@
 import Data.Monoid
 import Data.Maybe (fromJust)
 
-import Data.Convertible
+-- import Data.Convertible
+import Data.Convertible.Base
 import Data.Typeable
 
 -- import Language.Haskell.TH
@@ -315,7 +316,7 @@
 getValueOrThrowErrorsNCE sample_es v =
   case ensureNoCE sample_es v of
     (Just vNCE, es) | not (hasCertainError es) -> vNCE
-    (_, es) -> error (show es)
+    _ -> error (show v)
 
 {-|
   Add error collection support to an unary function whose
diff --git a/src/Data/Convertible/Base.hs b/src/Data/Convertible/Base.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Convertible/Base.hs
@@ -0,0 +1,121 @@
+{- 
+Borrowed from package convertible-1.1.1.0.  
+
+We cannot use convertible directly as some of its dependencies do not compile on ghcjs.
+-}
+
+{-
+Copyright (C) 2009-2011 John Goerzen <jgoerzen@complete.org>
+
+All rights reserved.
+
+For license and copyright information, see the file LICENSE in package convertible.
+
+-}
+
+{- |
+   Module     : Data.Convertible.Base
+   Copyright  : Copyright (C) 2009-2011 John Goerzen
+   License    : BSD3
+
+   Maintainer : John Goerzen <jgoerzen@complete.org>
+   Stability  : provisional
+   Portability: portable
+
+-}
+
+module Data.Convertible.Base( -- * The conversion process
+                              convert,
+                              Convertible(..),
+                              -- * Handling the results
+                              ConvertResult,
+                              ConvertError(..),
+                              convError,
+                              prettyConvertError
+                             )
+where
+import Prelude
+import Control.Monad.Error
+import Data.Typeable
+
+{- | The result of a safe conversion via 'safeConvert'. -}
+type ConvertResult a = Either ConvertError a
+
+----------------------------------------------------------------------
+-- Conversions
+----------------------------------------------------------------------
+
+{- | A typeclass that represents something that can be converted.
+A @Convertible a b@ instance represents an @a@ that can be converted to a @b@. -}
+class Convertible a b where
+    {- | Convert @a@ to @b@, returning Right on success and Left on error.
+       For a simpler interface, see 'convert'. -}
+    safeConvert :: a -> ConvertResult b
+
+{-
+{- | Any type can be converted to itself. -}
+instance Convertible a a where
+    safeConvert x = return x
+-}
+
+{-
+{- | Lists of any convertible type can be converted. -}
+instance Convertible a b => Convertible [a] [b] where
+    safeConvert = mapM safeConvert
+-}
+
+{- | Convert from one type of data to another.  Raises an exception if there is
+an error with the conversion.  For a function that does not raise an exception
+in that case, see 'safeConvert'. -}
+convert :: Convertible a b => a -> b
+convert x = 
+    case safeConvert x of
+      Left e -> error (prettyConvertError e)
+      Right r -> r
+
+{-
+instance Convertible Int Double where
+    safeConvert = return . fromIntegral
+instance Convertible Double Int where
+    safeConvert = return . truncate         -- could do bounds checking here
+instance Convertible Integer Double where
+    safeConvert = return . fromIntegral
+instance Convertible Double Integer where
+    safeConvert = return . truncate
+-}
+
+----------------------------------------------------------------------
+-- Error Handling
+----------------------------------------------------------------------
+
+{- | How we indicate that there was an error. -}
+data ConvertError = ConvertError {
+      convSourceValue :: String,
+      convSourceType :: String,
+      convDestType :: String,
+      convErrorMessage :: String}
+                    deriving (Eq, Read, Show)
+
+instance Error ConvertError where
+    strMsg x = ConvertError "(unknown)" "(unknown)" "(unknown)" x
+
+convError' :: (Show a, Typeable a, Typeable b) =>
+               String -> a -> b -> ConvertResult b
+convError' msg inpval retval = 
+     Left $ ConvertError {
+             convSourceValue = show inpval,
+             convSourceType = show . typeOf $ inpval,
+             convDestType = show . typeOf $ retval,
+             convErrorMessage = msg}
+    
+convError :: (Show a, Typeable a, Typeable b) =>
+             String -> a -> ConvertResult b
+convError msg inpval = 
+    convError' msg inpval undefined
+    
+prettyConvertError :: ConvertError -> String
+prettyConvertError (ConvertError sv st dt em) =
+    "Convertible: error converting source data " ++ sv ++ " of type " ++ st
+    ++ " to type " ++ dt ++ ": " ++ em
+    
+
diff --git a/src/Data/Convertible/Instances/Num.hs b/src/Data/Convertible/Instances/Num.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Convertible/Instances/Num.hs
@@ -0,0 +1,679 @@
+{- 
+Borrowed from package convertible-1.1.1.0.  
+
+We cannot use convertible directly as some of its dependencies do not compile on ghcjs.
+-}
+
+{- |
+   Module     : Data.Convertible.Instances.Num
+   Copyright  : Copyright (C) 2009-2011 John Goerzen
+   License    : BSD3
+
+   Maintainer : John Goerzen <jgoerzen@complete.org>
+   Stability  : provisional
+   Portability: portable
+
+Numeric instances for Convertible.
+
+Copyright (C) 2009-2011 John Goerzen <jgoerzen@complete.org>
+
+All rights reserved.
+
+For license and copyright information, see the file LICENSE
+
+These instances perform conversion between numeric types such as Double, Int, Integer,
+Rational, and the like.  Here are some notes about the conversion process:
+
+Conversions from floating-point types such as Double to integral types are done via the
+'truncate' function.  This is a somewhat arbitrary decision; if you need different
+behavior, you will have to write your own instance or manually perform the conversion.
+
+All conversions perform bounds checking.  If a value is too large for its destination
+type, you will get a 'ConvertError' informing you of this.  Note that this behavior
+differs from functions in the Haskell standard libraries, which will perform the
+conversion without error, but give you garbage in the end.
+
+Conversions do not perform precision checking; loss of precision is implied with certain
+conversions (for instance, Double to Float) and this is not an error.
+-}
+
+module Data.Convertible.Instances.Num()
+where
+
+import Prelude
+import Data.Convertible.Base
+import Data.Convertible.Utils
+import Data.Int
+import Data.Word
+
+------------------------------------------------------------
+
+{- The following instances generated by this code:
+
+fp = ["Double", "Float", "Rational"]
+int = ["Int", "Int8", "Int16", "Int32", "Int64", "Word", "Word8", "Word16", "Word32",
+       "Word64"]
+allItems l1 l2 = concatMap (\x -> map (\y -> (x, y)) int) fp
+work = allItems fp int
+printIt (f, i) = 
+    "instance Convertible " ++ f ++ " " ++ i ++ " where \n\
+    \    safeConvert = boundedConversion (return . truncate)\n\
+    \instance Convertible " ++ i ++ " " ++ f ++ " where \n\
+    \    safeConvert = return . fromIntegral\n"
+
+main = mapM_ (putStrLn . printIt) work
+-}
+
+instance Convertible Double Int where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int Double where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Double Int8 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int8 Double where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Double Int16 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int16 Double where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Double Int32 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int32 Double where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Double Int64 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int64 Double where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Double Word where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word Double where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Double Word8 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word8 Double where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Double Word16 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word16 Double where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Double Word32 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word32 Double where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Double Word64 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word64 Double where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Float Int where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int Float where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Float Int8 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int8 Float where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Float Int16 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int16 Float where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Float Int32 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int32 Float where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Float Int64 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int64 Float where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Float Word where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word Float where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Float Word8 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word8 Float where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Float Word16 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word16 Float where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Float Word32 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word32 Float where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Float Word64 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word64 Float where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Rational Int where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int Rational where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Rational Int8 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int8 Rational where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Rational Int16 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int16 Rational where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Rational Int32 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int32 Rational where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Rational Int64 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Int64 Rational where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Rational Word where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word Rational where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Rational Word8 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word8 Rational where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Rational Word16 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word16 Rational where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Rational Word32 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word32 Rational where 
+    safeConvert = return . fromIntegral
+
+instance Convertible Rational Word64 where 
+    safeConvert = boundedConversion (return . truncate)
+instance Convertible Word64 Rational where 
+    safeConvert = return . fromIntegral
+
+
+------------------------------------------------------------
+{- The following instances generated by this code:
+
+int = ["Int", "Int8", "Int16", "Int32", "Int64", "Word", "Word8", "Word16", "Word32",
+       "Word64"]
+allItems l1 l2 = concatMap (\x -> map (\y -> (x, y)) l1) l2
+work = filter (\(a, b) -> a /= b) (allItems int int)
+printIt (f, i) = 
+    "instance Convertible " ++ f ++ " " ++ i ++ " where \n\
+    \    safeConvert = boundedConversion (return . fromIntegral)\n"
+
+printInteger i =
+    "instance Convertible Integer " ++ i ++ " where \n\
+    \    safeConvert = boundedConversion (return . fromIntegral)\n\
+    \instance Convertible " ++ i ++ " Integer where \n\
+    \    safeConvert = return . fromIntegral\n\n"
+
+main = do mapM_ (putStrLn . printIt) work
+          mapM_ (putStrLn . printInteger) int
+-}
+
+instance Convertible Int Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int Word where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int8 Int where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int8 Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int8 Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int8 Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int8 Word where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int8 Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int8 Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int8 Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int8 Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int16 Int where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int16 Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int16 Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int16 Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int16 Word where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int16 Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int16 Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int16 Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int16 Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int32 Int where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int32 Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int32 Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int32 Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int32 Word where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int32 Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int32 Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int32 Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int32 Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int64 Int where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int64 Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int64 Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int64 Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int64 Word where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int64 Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int64 Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int64 Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Int64 Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word Int where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word8 Int where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word8 Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word8 Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word8 Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word8 Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word8 Word where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word8 Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word8 Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word8 Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word16 Int where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word16 Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word16 Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word16 Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word16 Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word16 Word where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word16 Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word16 Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word16 Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word32 Int where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word32 Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word32 Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word32 Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word32 Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word32 Word where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word32 Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word32 Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word32 Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word64 Int where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word64 Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word64 Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word64 Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word64 Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word64 Word where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word64 Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word64 Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Word64 Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+
+instance Convertible Integer Int where 
+    safeConvert = boundedConversion (return . fromIntegral)
+instance Convertible Int Integer where 
+    safeConvert = return . fromIntegral
+
+
+instance Convertible Integer Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+instance Convertible Int8 Integer where 
+    safeConvert = return . fromIntegral
+
+
+instance Convertible Integer Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+instance Convertible Int16 Integer where 
+    safeConvert = return . fromIntegral
+
+
+instance Convertible Integer Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+instance Convertible Int32 Integer where 
+    safeConvert = return . fromIntegral
+
+
+instance Convertible Integer Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+instance Convertible Int64 Integer where 
+    safeConvert = return . fromIntegral
+
+
+instance Convertible Integer Word where 
+    safeConvert = boundedConversion (return . fromIntegral)
+instance Convertible Word Integer where 
+    safeConvert = return . fromIntegral
+
+
+instance Convertible Integer Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+instance Convertible Word8 Integer where 
+    safeConvert = return . fromIntegral
+
+
+instance Convertible Integer Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+instance Convertible Word16 Integer where 
+    safeConvert = return . fromIntegral
+
+
+instance Convertible Integer Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+instance Convertible Word32 Integer where 
+    safeConvert = return . fromIntegral
+
+
+instance Convertible Integer Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral)
+instance Convertible Word64 Integer where 
+    safeConvert = return . fromIntegral
+
+
+------------------------------------------------------------
+
+instance Convertible Integer Double where
+    safeConvert = return . fromIntegral
+instance Convertible Integer Float where
+    safeConvert = return . fromIntegral
+instance Convertible Integer Rational where
+    safeConvert = return . fromIntegral
+instance Convertible Double Integer where
+    safeConvert = return . truncate
+instance Convertible Float Integer where
+    safeConvert = return . truncate
+instance Convertible Rational Integer where
+    safeConvert = return . truncate
+
+instance Convertible Float Double where
+    safeConvert = return . realToFrac
+instance Convertible Double Float where
+    safeConvert = return . realToFrac
+instance Convertible Float Rational where
+    safeConvert = return . toRational
+instance Convertible Rational Float where
+    safeConvert = return . fromRational
+instance Convertible Double Rational where
+    safeConvert = return . toRational
+instance Convertible Rational Double where
+    safeConvert = return . fromRational
+
+------------------------------------------------------------
+instance Convertible Char Integer where
+    safeConvert = return . fromIntegral . fromEnum
+instance Convertible Integer Char where
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+------------------------------------------------------------
+{- These instances generated by:
+
+int = ["Int", "Int8", "Int16", "Int32", "Int64", "Word", "Word8", "Word16", "Word32",
+       "Word64"]
+printIt i = 
+    "instance Convertible Char " ++ i ++ " where \n\
+    \    safeConvert = boundedConversion (return . fromIntegral . fromEnum)\n\
+    \instance Convertible " ++ i ++ " Char where \n\
+    \    safeConvert = boundedConversion (return . toEnum . fromIntegral)\n\n"
+
+main = do mapM_ (putStrLn . printIt) int
+-}
+
+instance Convertible Char Int where 
+    safeConvert = boundedConversion (return . fromIntegral . fromEnum)
+instance Convertible Int Char where 
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+
+instance Convertible Char Int8 where 
+    safeConvert = boundedConversion (return . fromIntegral . fromEnum)
+instance Convertible Int8 Char where 
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+
+instance Convertible Char Int16 where 
+    safeConvert = boundedConversion (return . fromIntegral . fromEnum)
+instance Convertible Int16 Char where 
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+
+instance Convertible Char Int32 where 
+    safeConvert = boundedConversion (return . fromIntegral . fromEnum)
+instance Convertible Int32 Char where 
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+
+instance Convertible Char Int64 where 
+    safeConvert = boundedConversion (return . fromIntegral . fromEnum)
+instance Convertible Int64 Char where 
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+
+instance Convertible Char Word where 
+    safeConvert = boundedConversion (return . fromIntegral . fromEnum)
+instance Convertible Word Char where 
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+
+instance Convertible Char Word8 where 
+    safeConvert = boundedConversion (return . fromIntegral . fromEnum)
+instance Convertible Word8 Char where 
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+
+instance Convertible Char Word16 where 
+    safeConvert = boundedConversion (return . fromIntegral . fromEnum)
+instance Convertible Word16 Char where 
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+
+instance Convertible Char Word32 where 
+    safeConvert = boundedConversion (return . fromIntegral . fromEnum)
+instance Convertible Word32 Char where 
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+
+instance Convertible Char Word64 where 
+    safeConvert = boundedConversion (return . fromIntegral . fromEnum)
+instance Convertible Word64 Char where 
+    safeConvert = boundedConversion (return . toEnum . fromIntegral)
+
+
+instance Convertible Integer Integer where
+    safeConvert = return . id
+
diff --git a/src/Data/Convertible/Utils.hs b/src/Data/Convertible/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Convertible/Utils.hs
@@ -0,0 +1,83 @@
+{- 
+Borrowed from package convertible-1.1.1.0.  
+
+We cannot use convertible directly as some of its dependencies do not compile on ghcjs.
+-}
+
+{-
+Copyright (C) 2009-2011 John Goerzen <jgoerzen@complete.org>
+
+All rights reserved.
+
+For license and copyright information, see the file LICENSE
+
+-}
+
+{- |
+   Module     : Data.Convertible.Utils
+   Copyright  : Copyright (C) 2009-2011 John Goerzen
+   License    : BSD3
+
+   Maintainer : John Goerzen <jgoerzen@complete.org>
+   Stability  : provisional
+   Portability: portable
+
+-}
+
+module Data.Convertible.Utils(boundedConversion,
+                             convertVia
+                             )
+where
+import Prelude
+import Data.Convertible.Base
+import Data.Typeable
+
+{- | Utility function to perform bounds checking as part of a conversion.
+
+Does this be examining the bounds of the destination type, converting to the type of
+the source via 'safeConvert', comparing to the source value.  Results in an error
+if the conversion is out of bounds. -}
+boundedConversion :: (Ord a, Bounded b, Show a, Show b, Convertible a Integer,
+                      Convertible b Integer,
+                      Typeable a, Typeable b) => 
+                     (a -> ConvertResult b) -- ^ Function to do the conversion
+                  -> a                      -- ^ Input data
+                  -> ConvertResult b        -- ^ Result
+boundedConversion (func :: (a -> ConvertResult b)) inp =
+    do result <- func inp
+       let smallest = asTypeOf minBound result
+       let biggest = asTypeOf maxBound result
+       let smallest' = (convert smallest)::Integer
+       let biggest' = (convert biggest)::Integer
+       let inp' = (convert inp)::Integer
+       if inp' < smallest' || inp' > biggest'
+          then convError ("Input value outside of bounds: " ++ show (smallest, biggest))
+               inp :: ConvertResult b
+          else return result :: ConvertResult b
+
+ifThenElse :: Bool -> t -> t -> t
+ifThenElse b c d = if b then c else d
+
+{- | Useful for defining conversions that are implemented in terms of other
+conversions via an intermediary type. Instead of:
+
+>instance Convertible CalendarTime POSIXTime where
+>    safeConvert a = do r <- safeConvert a
+>                       safeConvert (r :: ClockTime)
+
+we can now write:
+
+>instance Convertible CalendarTime POSIXTime where
+>    safeConvert = convertVia (undefined::ClockTime)
+
+which does the same thing -- converts a CalendarTime to a ClockTime, then a
+ClockTime to a POSIXTime, both using existing 'Convertible' instances.
+ -}
+convertVia :: (Convertible a b, Convertible b c) =>
+              b                 -- ^ Dummy data to establish intermediate type - can be undefined
+           -> a                 -- ^ Input value
+           -> ConvertResult c   -- ^ Result
+convertVia dummy inp =
+    do r1 <- safeConvert inp
+       safeConvert (asTypeOf r1 dummy)
+
diff --git a/src/MixedTypesNumPrelude.hs b/src/MixedTypesNumPrelude.hs
--- a/src/MixedTypesNumPrelude.hs
+++ b/src/MixedTypesNumPrelude.hs
@@ -38,6 +38,8 @@
 
   -- * Re-exporting Prelude, hiding the operators we are changing
   module Numeric.MixedTypes.PreludeHiding,
+  -- * A part of package ``convertible''
+  module Data.Convertible.Base,
   -- * Modules with Prelude alternatives
   module Numeric.MixedTypes.Literals,
   module Numeric.MixedTypes.Bool,
@@ -59,6 +61,8 @@
 where
 
 import Data.Ratio ((%))
+import Data.Convertible.Instances.Num()
+import Data.Convertible.Base
 import Utils.TH.DeclForTypes
 import Utils.Test.EnforceRange
 import Numeric.CollectErrors
diff --git a/src/Numeric/MixedTypes/Elementary.hs b/src/Numeric/MixedTypes/Elementary.hs
--- a/src/Numeric/MixedTypes/Elementary.hs
+++ b/src/Numeric/MixedTypes/Elementary.hs
@@ -168,13 +168,15 @@
         let x = enforceRange (Just (-100000), Just 100000) x_ in
           exp x ?>=?$ 0
     it "exp(-x) == 1/(exp x)" $ do
-      property $ \ (x :: t) ->
-        ((-100000) !<! x && x !<! 100000) ==>
-          (exp x !>! 0) ==>
-            (ensureCN $ exp (-x)) ?==?$ 1/(exp x)
+      property $ \ (x_ :: t) ->
+        let x = enforceRange (Just (-100000), Just 100000) x_ in
+        let ex = exp x in
+          (ex !>! 0) ==>
+            (ensureCN $ exp (-x)) ?==?$ 1/ex
     it "exp(x+y) = exp(x)*exp(y)" $ do
-      property $ \ (x :: t)  (y :: t) ->
-        ((-100000) !<! x && x !<! 100000 && (-100000) !<! y && y !<! 100000) ==>
+      property $ \ (x_ :: t)  (y_ :: t) ->
+        let x = enforceRange (Just (-100000), Just 100000) x_ in
+        let y = enforceRange (Just (-100000), Just 100000) y_ in
           (exp $ x + y) ?==?$ (exp x) * (exp y)
   where
   infix 4 ?==?$
@@ -230,6 +232,7 @@
    CanTestCertainly
      (EqCompareType (LogType (DivType Integer t)) (LogType t)),
    CanTestCertainly (OrderCompareType (MulType t t) Integer),
+   CanTestCertainly (OrderCompareType (ExpType t) Integer),
    CanTestCertainly
      (EqCompareType
         (LogType (MulType t t)) (AddType (LogType t) (LogType t))),
@@ -243,26 +246,33 @@
    HasOrderAsymmetric t Integer,
    HasOrderAsymmetric (DivType Integer t) Integer,
    HasOrderAsymmetric (MulType t t) Integer,
+   HasOrderAsymmetric (ExpType t) Integer,
    HasOrderAsymmetric Integer t,
    CanAddAsymmetric (LogType t) (LogType t), CanMulAsymmetric t t,
    CanDiv Integer t, CanExp t, CanLog t, CanLog (DivType Integer t),
    CanLog (MulType t t), CanLog (ExpType t),
-   LogType t ~ NegType (LogType t)) =>
+   LogType t ~ NegType (LogType t),
+   CanEnforceRange t Integer) =>
   T t -> Spec
 specCanLogReal (T typeName :: T t) =
   describe (printf "CanLog %s" typeName) $ do
     it "log(1/x) == -(log x)" $ do
-      property $ \ (x :: t) ->
+      property $ \ (x_ :: t) ->
+        let x = enforceRange (Just 0, Nothing) x_ in
         x !>! 0 && (1/x) !>! 0  ==>
           log (1/x) ?==?$ -(log x)
     it "log(x*y) = log(x)+log(y)" $ do
-      property $ \ (x :: t)  (y :: t) ->
+      property $ \ (x_ :: t)  (y_ :: t) ->
+        let x = enforceRange (Just 0, Nothing) x_ in
+        let y = enforceRange (Just 0, Nothing) y_ in
         x !>! 0 && y !>! 0 && x*y !>! 0  ==>
           (log $ x * y) ?==?$ (log x) + (log y)
     it "log(exp x) == x" $ do
-      property $ \ (x :: t) ->
-        ((-100000) !<! x && x !<! 100000) ==>
-          log (exp x) ?==?$ x
+      property $ \ (x_ :: t) ->
+        let x = enforceRange (Just (-1000), Just 10000) x_ in
+        let ex = exp x in
+          (ex !>! 0) ==>
+            log ex ?==?$ x
   where
   infix 4 ?==?$
   (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
diff --git a/src/Numeric/MixedTypes/Literals.hs b/src/Numeric/MixedTypes/Literals.hs
--- a/src/Numeric/MixedTypes/Literals.hs
+++ b/src/Numeric/MixedTypes/Literals.hs
@@ -65,7 +65,9 @@
 import qualified Prelude as P
 import Text.Printf
 
-import Data.Convertible (Convertible(..), convert, ConvertResult, ConvertError, convError)
+-- import Data.Convertible (Convertible(..), convert, ConvertResult, ConvertError, convError)
+import Data.Convertible.Base
+import Data.Convertible.Instances.Num ()
 
 import qualified Data.List as List
 
diff --git a/src/Numeric/MixedTypes/MinMaxAbs.hs b/src/Numeric/MixedTypes/MinMaxAbs.hs
--- a/src/Numeric/MixedTypes/MinMaxAbs.hs
+++ b/src/Numeric/MixedTypes/MinMaxAbs.hs
@@ -97,6 +97,7 @@
     (EqCompareType
        (MinMaxType t1 (MinMaxType t2 t3))
        (MinMaxType (MinMaxType t1 t2) t3)),
+  CanTestFinite t1, CanTestFinite t2, CanTestFinite t3,
   HasEqAsymmetric t1 t1, HasEqAsymmetric t2 t2,
   HasEqAsymmetric t3 t3,
   HasEqAsymmetric (MinMaxType t1 t2) (MinMaxType t2 t1),
@@ -116,35 +117,43 @@
   describe (printf "CanMinMax %s %s, CanMinMax %s %s" typeName1 typeName2 typeName2 typeName3) $ do
     it "`min` is not larger than its arguments" $ do
       property $ \ (x :: t1) (y :: t2) ->
-        (x ?==? x) && (y ?==? y) ==> -- avoid NaN
+        -- (x ?==? x) && (y ?==? y) ==> -- avoid NaN
+        (isFinite x) && (isFinite y) ==>
           let m = x `min` y in (m ?<=?$ y) .&&. (m ?<=?$ x)
     it "`max` is not smaller than its arguments" $ do
       property $ \ (x :: t1) (y :: t2) ->
-        (x ?==? x) && (y ?==? y) ==> -- avoid NaN
+        -- (x ?==? x) && (y ?==? y) ==> -- avoid NaN
+        (isFinite x) && (isFinite y) ==>
           let m = x `max` y in (m ?>=?$ y) .&&. (m ?>=?$ x)
     it "has idempotent `min`" $ do
       property $ \ (x :: t1) ->
-        (x ?==? x) ==> -- avoid NaN
+        -- (x ?==? x) ==> -- avoid NaN
+        (isFinite x) ==>
           (x `min` x) ?==?$ x
     it "has idempotent `max`" $ do
       property $ \ (x :: t1) ->
-        (x ?==? x) ==> -- avoid NaN
+        -- (x ?==? x) ==> -- avoid NaN
+        (isFinite x) ==>
           (x `max` x) ?==?$ x
     it "has commutative `min`" $ do
       property $ \ (x :: t1) (y :: t2) ->
-        (x ?==? x) && (y ?==? y) ==> -- avoid NaN
+        -- (x ?==? x) && (y ?==? y) ==> -- avoid NaN
+        (isFinite x) && (isFinite y) ==>
           (x `min` y) ?==?$ (y `min` x)
     it "has commutative `max`" $ do
       property $ \ (x :: t1) (y :: t2) ->
-        (x ?==? x) && (y ?==? y) ==> -- avoid NaN
+        -- (x ?==? x) && (y ?==? y) ==> -- avoid NaN
+        (isFinite x) && (isFinite y) ==>
           (x `max` y) ?==?$ (y `max` x)
     it "has associative `min`" $ do
       property $ \ (x :: t1) (y :: t2) (z :: t3) ->
-        (x ?==? x) && (y ?==? y) && (z ?==? z) ==> -- avoid NaN
+        -- (x ?==? x) && (y ?==? y) && (z ?==? z) ==> -- avoid NaN
+        (isFinite x) && (isFinite y) && (isFinite z) ==>
             (x `min` (y `min` z)) ?==?$ ((x `min` y) `min` z)
     it "has associative `max`" $ do
       property $ \ (x :: t1) (y :: t2) (z :: t3) ->
-        (x ?==? x) && (y ?==? y) && (z ?==? z) ==> -- avoid NaN
+        -- (x ?==? x) && (y ?==? y) && (z ?==? z) ==> -- avoid NaN
+        (isFinite x) && (isFinite y) && (isFinite z) ==>
             (x `max` (y `max` z)) ?==?$ ((x `max` y) `max` z)
   where
   (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
@@ -170,6 +179,7 @@
     (EqCompareType
        (MinMaxType t (MinMaxType t t))
        (MinMaxType (MinMaxType t t) t)),
+  CanTestFinite t,
   HasEqAsymmetric t t, HasEqAsymmetric (MinMaxType t t) t,
   HasEqAsymmetric (MinMaxType t t) (MinMaxType t t),
   HasEqAsymmetric
@@ -290,6 +300,7 @@
    ConvertibleExactly Integer t,
    HasEqCertainly t t,
    HasEqCertainly t (NegType t),
+   CanTestFinite t,
    CanTestPosNeg t,
    CanTestPosNeg (NegType t)
   )
@@ -305,9 +316,11 @@
       let z = convertExactly 0 :: t in negate z ?==? z
     it "takes positive to negative" $ do
       property $ \ (x :: t) ->
+        (isFinite x) ==> -- avoid NaN
         (isCertainlyPositive x) ==> (isCertainlyNegative (negate x))
     it "takes negative to positive" $ do
       property $ \ (x :: t) ->
+        (isFinite x) ==> -- avoid NaN
         (isCertainlyNegative x) ==> (isCertainlyPositive (negate x))
   where
   (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
@@ -362,7 +375,7 @@
   HSpec properties that each implementation of CanAbs should satisfy.
  -}
 specCanAbs ::
-  (CanAbsX t, CanAbsX (AbsType t))
+  (CanAbsX t, CanAbsX (AbsType t), CanTestFinite t)
   =>
   T t -> Spec
 specCanAbs (T typeName :: T t) =
@@ -373,12 +386,16 @@
           (abs (abs x)) ?==?$ (abs x)
     it "is identity on non-negative arguments" $ do
       property $ \ (x :: t) ->
+        (isFinite x) ==>
         isCertainlyNonNegative x  ==> x ?==?$ (abs x)
     it "is negation on non-positive arguments" $ do
       property $ \ (x :: t) ->
+        (isFinite x) ==>
         isCertainlyNonPositive x  ==> (negate x) ?==?$ (abs x)
     it "does not give negative results" $ do
-      property $ \ (x :: t) -> not $ isCertainlyNegative (abs x)
+      property $ \ (x :: t) -> 
+        (isFinite x) ==>
+        not $ isCertainlyNegative (abs x)
   where
   (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
   (?==?$) = printArgsIfFails2 "?==?" (?==?)
diff --git a/src/Utils/Test/EnforceRange.hs b/src/Utils/Test/EnforceRange.hs
--- a/src/Utils/Test/EnforceRange.hs
+++ b/src/Utils/Test/EnforceRange.hs
@@ -26,10 +26,11 @@
 import Numeric.MixedTypes.MinMaxAbs
 import Numeric.MixedTypes.AddSub
 import Numeric.MixedTypes.Ring
+import Numeric.MixedTypes.Field
 import Numeric.MixedTypes.Round
 
 type CanEnforceRange t b =
-    (CanAddSubMulBy t Integer
+    (CanAddSubMulDivCNBy t Integer
     , CanAddSameType t, CanSubSameType t, CanAbsSameType t
     , CanDivIModIntegerSameType t
     , ConvertibleExactly b t
@@ -44,12 +45,14 @@
 enforceRange ::
     (CanEnforceRange t b) => (Maybe b, Maybe b) -> t -> t
 enforceRange (Just l_, Just u_) (a::t) 
-    | not (l + 1 !<! u) = error "enforceRange: inconsistent range"
+    | not (l !<! u) = error "enforceRange: inconsistent range"
     | l !<! a && a !<! u = a
-    | otherwise = l + 1 + ((abs a) `modNoCN` (u-l-1))
+    | l !<! b && b !<! u = b
+    | otherwise = (u-l)/!2
     where
     l = convertExactly l_ :: t
     u = convertExactly u_ :: t
+    b = l + ((abs a) `modNoCN` (u-l))
 enforceRange (Just l_, _) (a::t)
     | l !<! a = a
     | otherwise = (2*l-a+1)
