mixed-types-num-0.5.12: src/Data/Convertible/Base.hs
{-# OPTIONS_GHC -Wno-deprecations #-}
{-
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 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)
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