numeric-prelude 0.4.1 → 0.4.2
raw patch · 19 files changed
+289/−78 lines, 19 filesdep ~basedep ~deepseqdep ~random
Dependency ranges changed: base, deepseq, random
Files
- docs/NOTES +31/−0
- numeric-prelude.cabal +12/−11
- src/Algebra/Module.hs +8/−1
- src/Algebra/Monoid.hs +5/−0
- src/Algebra/NormedSpace/Euclidean.hs +11/−0
- src/Algebra/NormedSpace/Maximum.hs +6/−0
- src/Algebra/NormedSpace/Sum.hs +6/−0
- src/Algebra/VectorSpace.hs +4/−0
- src/Number/Physical.hs +7/−2
- src/Number/Physical/Unit.hs +1/−1
- src/Number/Positional.hs +10/−8
- src/Number/Positional/Check.hs +7/−7
- src/Number/Quaternion.hs +13/−13
- src/Number/Ratio.hs +2/−2
- src/Number/ResidueClass/Check.hs +9/−9
- src/Number/ResidueClass/Func.hs +9/−9
- src/Number/ResidueClass/Maybe.hs +7/−7
- src/Number/ResidueClass/Reader.hs +9/−1
- src/NumericPrelude/Base.hs +132/−7
docs/NOTES view
@@ -1,3 +1,34 @@+* Positional: test suite++* Positional and zero++Represent zero with empty mantissa?+Or better have NonZero type with non-empty mantissa+and a full number type with optional zero?+Or something where we can have negative numbers and zero as option?+Problem is, that we allow negative digits+and thus even a Positive number type can represent zero and negative numbers.++We might at least define a NonEmptyMantissa type for interim computations,+like in 'divide'.++* Positional.Fixed++We could derive the base from digit type, e.g.+ Int32 -> 1000+ Int64 -> 1000000+ newtype Integer -> anything++* Algebra.Module++I think it should be a type family rather than a multi-parameter type class.+My main motivation for multi-paramter type class+was to allow complex numbers to be a vector space over both real and complex numbers.+This does not worked well and even more type inference often fails.+We should just have two different types of complex numbers:+One complex number type being a vector space over reals+and another complex type being a vector space over complex numbers.+ * zipWithChecked We could make the second operand lazy,
numeric-prelude.cabal view
@@ -1,5 +1,5 @@ Name: numeric-prelude-Version: 0.4.1+Version: 0.4.2 License: BSD3 License-File: LICENSE Author: Dylan Thurston <dpt@math.harvard.edu>, Henning Thielemann <numericprelude@henning-thielemann.de>, Mikael Johansson@@ -8,7 +8,7 @@ Category: Math Stability: Experimental Tested-With: GHC==6.4.1, GHC==6.8.2, GHC==6.10.4, GHC==6.12.3-Tested-With: GHC==7.2.2, GHC==7.4.1, GHC==7.6.3+Tested-With: GHC==7.2.2, GHC==7.4.1, GHC==7.6.3, GHC==7.8.4, GHC==7.10.1 Cabal-Version: >=1.8 Build-Type: Simple Synopsis: An experimental alternative hierarchy of numeric type classes@@ -146,12 +146,12 @@ docs/README src/Algebra/GenerateRules.hs -Flag buildTests- description: Build test executables+Flag buildExamples+ description: Build example executables default: False Source-Repository this- Tag: 0.4.1+ Tag: 0.4.2 Type: darcs Location: http://code.haskell.org/numeric-prelude/ @@ -166,13 +166,13 @@ storable-record >=0.0.1 && <0.1, non-negative >=0.0.5 && <0.2, utility-ht >=0.0.6 && <0.1,- deepseq >=1.1 && <1.4+ deepseq >=1.1 && <1.5 -- splitBase Build-Depends: array >=0.1 && <0.6, containers >=0.1 && <0.6,- random >=1.0 && <1.1,+ random >=1.0 && <1.2, base >= 2 && <5 If impl(ghc>=7.0)@@ -288,7 +288,7 @@ GHC-Options: -Wall Main-Is: Demo.hs - If flag(buildTests)+ If flag(buildExamples) Build-Depends: numeric-prelude, base@@ -299,7 +299,8 @@ CPP-Options: -DNoImplicitPrelude=RebindableSyntax Extensions: CPP -Executable numeric-prelude-test+Test-Suite numeric-prelude-test+ Type: exitcode-stdio-1.0 Hs-Source-Dirs: test, gaussian GHC-Options: -Wall Other-modules:@@ -320,7 +321,7 @@ Number.ComplexSquareRoot Main-Is: Test/Run.hs - If flag(buildTests)+ If flag(buildExamples) Build-Depends: HUnit >=1 && <2, numeric-prelude,@@ -344,7 +345,7 @@ MathObj.Gaussian.Bell MathObj.Gaussian.Polynomial - If flag(buildTests)+ If flag(buildExamples) Build-Depends: gnuplot >=0.5 && <0.6, HTam >=0.0.2 && <0.1,
src/Algebra/Module.hs view
@@ -28,13 +28,15 @@ import qualified NumericPrelude.Elementwise as Elem import Control.Applicative (Applicative(pure, (<*>)), ) +import qualified Data.Complex as Complex98+ import Data.Function.HT (powerAssociative, ) import Data.List (map, zipWith, ) import Data.Tuple.HT (fst3, snd3, thd3, ) import Data.Tuple (fst, snd, ) +import qualified Prelude as P import Prelude((.), Eq, Bool, Int, Integer, Float, Double, ($), )--- import qualified Prelude as P -- Is this right?@@ -116,6 +118,11 @@ instance (C a v) => C a (c -> v) where {-# INLINE (*>) #-} (*>) s f = (*>) s . f+++instance (C a b, P.RealFloat b) => C a (Complex98.Complex b) where+ {-# INLINE (*>) #-}+ s *> (x Complex98.:+ y) = (s *> x) Complex98.:+ (s *> y) {-* Related functions -}
src/Algebra/Monoid.hs view
@@ -18,6 +18,11 @@ import Data.Monoid as Mn +import Data.Function ((.))+import Data.List (foldr, reverse, map)+import Prelude ()++ {- | We expect a monoid to adher to associativity and the identity behaving decently.
src/Algebra/NormedSpace/Euclidean.hs view
@@ -10,6 +10,7 @@ import NumericPrelude.Base import NumericPrelude.Numeric (sqr, abs, zero, (+), sum, Float, Double, Int, Integer, )+import qualified Prelude as P import qualified Number.Ratio as Ratio @@ -18,6 +19,7 @@ import qualified Algebra.Absolute as Absolute import qualified Algebra.Module as Module +import qualified Data.Complex as Complex98 import qualified Data.Foldable as Fold @@ -116,4 +118,13 @@ normSqr = sum . map normSqr instance (Algebraic.C a, Sqr a v) => C a [v] where+ norm = defltNorm+++instance (Sqr a v, P.RealFloat v) => Sqr a (Complex98.Complex v) where+ normSqr (x0 Complex98.:+ x1) = normSqr x0 + normSqr x1++instance+ (Algebraic.C a, Sqr a v, P.RealFloat v) =>+ C a (Complex98.Complex v) where norm = defltNorm
src/Algebra/NormedSpace/Maximum.hs view
@@ -10,6 +10,7 @@ import NumericPrelude.Base import NumericPrelude.Numeric+import qualified Prelude as P import qualified Number.Ratio as Ratio @@ -18,6 +19,7 @@ import qualified Algebra.RealRing as RealRing import qualified Algebra.Module as Module +import qualified Data.Complex as Complex98 import qualified Data.Foldable as Fold @@ -76,3 +78,7 @@ we can use zero as identity element. norm = maximum . map norm -}+++instance (C a v, P.RealFloat v) => C a (Complex98.Complex v) where+ norm (x0 Complex98.:+ x1) = max (norm x0) (norm x1)
src/Algebra/NormedSpace/Sum.hs view
@@ -10,6 +10,7 @@ import NumericPrelude.Base import NumericPrelude.Numeric+import qualified Prelude as P import qualified Number.Ratio as Ratio @@ -18,6 +19,7 @@ import qualified Algebra.Additive as Additive import qualified Algebra.Module as Module +import qualified Data.Complex as Complex98 import qualified Data.Foldable as Fold @@ -81,3 +83,7 @@ instance (Additive.C a, C a v) => C a [v] where norm = sum . map norm+++instance (C a v, P.RealFloat v) => C a (Complex98.Complex v) where+ norm (x0 Complex98.:+ x1) = norm x0 + norm x1
src/Algebra/VectorSpace.hs view
@@ -8,6 +8,8 @@ import qualified Algebra.PrincipalIdealDomain as PID import qualified Number.Ratio as Ratio +import qualified Data.Complex as Complex98+ -- import NumericPrelude.Numeric import qualified Prelude as P @@ -32,3 +34,5 @@ instance (C a b) => C a [b] instance (C a b) => C a (c -> b)++instance (C a b, P.RealFloat b) => C a (Complex98.Complex b)
src/Number/Physical.hs view
@@ -16,7 +16,7 @@ import qualified Algebra.Transcendental as Trans import qualified Algebra.Algebraic as Algebraic import qualified Algebra.Field as Field-import qualified Algebra.Absolute as Absolute+import qualified Algebra.Absolute as Absolute import qualified Algebra.Ring as Ring import qualified Algebra.Additive as Additive import qualified Algebra.ZeroTestable as ZeroTestable@@ -25,7 +25,8 @@ import qualified Number.Ratio as Ratio -import Control.Monad(guard,liftM,liftM2)+import Control.Monad (guard, liftM, liftM2, ap)+import Control.Applicative (Applicative(pure, (<*>))) import Data.Maybe.HT(toMaybe) import Data.Maybe(fromMaybe)@@ -218,6 +219,10 @@ if Unit.isScalar xu then fromScalarSingle (f x) else error "Physics.Quantity.Value.fmap: function for scalars, only"++instance Applicative (T a) where+ (<*>) = ap+ pure = return instance Monad (T i) where (>>=) (Cons xu x) f =
src/Number/Physical/Unit.hs view
@@ -71,7 +71,7 @@ in toMaybe (denominator y == 1) (numerator y)) -{- impossible because Unit.T is a type synonyme but not a data type+{- impossible because Unit.T is a type synonym but not a data type instance Show (Unit.T i) where show = show.toVector -}
src/Number/Positional.hs view
@@ -589,20 +589,20 @@ {- * arithmetic -} -fromLaurent :: LPoly.T Int -> T+fromLaurent :: LPoly.T Digit -> T fromLaurent (LPoly.Cons nxe xm) = (NP.negate nxe, xm) -toLaurent :: T -> LPoly.T Int+toLaurent :: T -> LPoly.T Digit toLaurent (xe, xm) = LPoly.Cons (NP.negate xe) xm liftLaurent2 ::- (LPoly.T Int -> LPoly.T Int -> LPoly.T Int) ->+ (LPoly.T Digit -> LPoly.T Digit -> LPoly.T Digit) -> (T -> T -> T) liftLaurent2 f x y = fromLaurent (f (toLaurent x) (toLaurent y)) liftLaurentMany ::- ([LPoly.T Int] -> LPoly.T Int) ->+ ([LPoly.T Digit] -> LPoly.T Digit) -> ([T] -> T) liftLaurentMany f = fromLaurent . f . map toLaurent@@ -773,7 +773,9 @@ let (ye,ym) = until ((>=b) . abs . head . snd) (decreaseExp b) (ye',ym')- in nest 3 trimOnce (compress b (xe-ye, divMant b ym xm))+ in if null xm+ then (xe,xm)+ else nest 3 trimOnce (compress b (xe-ye, divMant b ym xm)) divMant :: Basis -> Mantissa -> Mantissa -> Mantissa divMant _ [] _ = error "Number.Positional: division by zero"@@ -811,7 +813,7 @@ Fast division for small integral divisors, which occur for instance in summands of power series. -}-divIntMant :: Basis -> Int -> Mantissa -> Mantissa+divIntMant :: Basis -> Digit -> Mantissa -> Mantissa divIntMant b y xInit = List.unfoldr (\(r,rxs) -> let rb = r*b@@ -824,7 +826,7 @@ (0,xInit) -- this version is simple but ignores the possibility of a terminating result-divIntMantInf :: Basis -> Int -> Mantissa -> Mantissa+divIntMantInf :: Basis -> Digit -> Mantissa -> Mantissa divIntMantInf b y = map fst . tail . scanl (\(_,r) x -> divMod (r*b+x) y) (undefined,0) .@@ -1308,7 +1310,7 @@ {- | Efficient computation of Arcus tangens of an argument of the form @1\/n@. -}-arctanStem :: Basis -> Int -> T+arctanStem :: Basis -> Digit -> T arctanStem b n = let x = (0, divIntMant b n [1]) divN2 = divInt b n . divInt b (-n)
src/Number/Positional/Check.hs view
@@ -48,7 +48,7 @@ and cannot be made unique in finite time. This way we avoid infinite carry ripples. -}-data T = Cons {base :: Int, exponent :: Int, mantissa :: Pos.Mantissa}+data T = Cons {base :: Pos.Basis, exponent :: Int, mantissa :: Pos.Mantissa} deriving (Show) @@ -74,7 +74,7 @@ in prependDigit (fst (head ys)) (Cons b ex digits) -prependDigit :: Int -> T -> T+prependDigit :: Pos.Digit -> T -> T prependDigit 0 x = x prependDigit x (Cons b ex xs) = Cons b (ex+1) (x:xs)@@ -83,15 +83,15 @@ {- * conversions -} -lift0 :: (Int -> Pos.T) -> T+lift0 :: (Pos.Basis -> Pos.T) -> T lift0 op = uncurry (Cons defltBase) (op defltBase) -lift1 :: (Int -> Pos.T -> Pos.T) -> T -> T+lift1 :: (Pos.Basis -> Pos.T -> Pos.T) -> T -> T lift1 op (Cons xb xe xm) = uncurry (Cons xb) (op xb (xe, xm)) -lift2 :: (Int -> Pos.T -> Pos.T -> Pos.T) -> T -> T -> T+lift2 :: (Pos.Basis -> Pos.T -> Pos.T -> Pos.T) -> T -> T -> T lift2 op (Cons xb xe xm) (Cons yb ye ym) = let b = commonBasis xb yb in uncurry (Cons b) (op b (xe, xm) (ye, ym))@@ -109,11 +109,11 @@ then xb else error "Number.Positional: bases differ" -fromBaseInteger :: Int -> Integer -> T+fromBaseInteger :: Pos.Basis -> Integer -> T fromBaseInteger b n = uncurry (Cons b) (Pos.fromBaseInteger b n) -fromBaseRational :: Int -> Rational -> T+fromBaseRational :: Pos.Basis -> Rational -> T fromBaseRational b r = uncurry (Cons b) (Pos.fromBaseRational b r)
src/Number/Quaternion.hs view
@@ -103,34 +103,34 @@ -- | The conjugate of a quaternion. {-# SPECIALISE conjugate :: T Double -> T Double #-}-conjugate :: (Additive.C a) => T a -> T a+conjugate :: (Additive.C a) => T a -> T a conjugate (Cons r i) = Cons r (negate i) -- | Scale a quaternion by a real number. {-# SPECIALISE scale :: Double -> T Double -> T Double #-}-scale :: (Ring.C a) => a -> T a -> T a+scale :: (Ring.C a) => a -> T a -> T a scale r (Cons xr xi) = Cons (r * xr) (scaleImag r xi) -- | like Module.*> but without additional class dependency-scaleImag :: (Ring.C a) => a -> (a,a,a) -> (a,a,a)+scaleImag :: (Ring.C a) => a -> (a,a,a) -> (a,a,a) scaleImag r (xi,xj,xk) = (r * xi, r * xj, r * xk) -- | the same as NormedEuc.normSqr but with a simpler type class constraint-normSqr :: (Ring.C a) => T a -> a+normSqr :: (Ring.C a) => T a -> a normSqr (Cons xr xi) = xr*xr + scalarProduct xi xi -norm :: (Algebraic.C a) => T a -> a+norm :: (Algebraic.C a) => T a -> a norm x = sqrt (normSqr x) -- | scale a quaternion into a unit quaternion-normalize :: (Algebraic.C a) => T a -> T a+normalize :: (Algebraic.C a) => T a -> T a normalize x = scale (recip (norm x)) x -scalarProduct :: (Ring.C a) => (a,a,a) -> (a,a,a) -> a+scalarProduct :: (Ring.C a) => (a,a,a) -> (a,a,a) -> a scalarProduct (xi,xj,xk) (yi,yj,yk) = xi*yi + xj*yj + xk*yk -crossProduct :: (Ring.C a) => (a,a,a) -> (a,a,a) -> (a,a,a)+crossProduct :: (Ring.C a) => (a,a,a) -> (a,a,a) -> (a,a,a) crossProduct (xi,xj,xk) (yi,yj,yk) = (xj*yk - xk*yj, xk*yi - xi*yk, xi*yj - xj*yi) @@ -140,11 +140,11 @@ @similarity (cos(a\/2) +:: scaleImag (sin(a\/2)) v) (0 +:: x) == (0 +:: y)@ where @y@ results from rotating @x@ around the axis @v@ by the angle @a@. -}-similarity :: (Field.C a) => T a -> T a -> T a+similarity :: (Field.C a) => T a -> T a -> T a similarity c x = c*x/c {--rotate :: (Field.C a) =>+rotate :: (Field.C a) => (a,a,a) {- ^ rotation axis, must be normalized -} -> T a -> T a@@ -265,9 +265,9 @@ instance (Ring.C a) => Ring.C (T a) where {-# SPECIALISE instance Ring.C (T Float) #-} {-# SPECIALISE instance Ring.C (T Double) #-}- one = Cons one zero- fromInteger = fromReal . fromInteger- (Cons xr xi) * (Cons yr yi) =+ one = Cons one zero+ fromInteger = fromReal . fromInteger+ (Cons xr xi) * (Cons yr yi) = Cons (xr*yr - scalarProduct xi yi) (scaleImag xr yi + scaleImag yr xi + crossProduct xi yi)
src/Number/Ratio.hs view
@@ -12,8 +12,8 @@ -} module Number.Ratio- (- T((:%), numerator, denominator), (%),+ (+ T((:%), numerator, denominator), (%), Rational, fromValue, recip,
src/Number/ResidueClass/Check.hs view
@@ -101,18 +101,18 @@ isZero (Cons _ r) = isZero r instance (Eq a, Integral.C a) => Additive.C (T a) where- zero = error "no generic zero in a residue class, use ResidueClass.zero"- (+) = lift2 Res.add- (-) = lift2 Res.sub- negate = lift1 Res.neg+ zero = error "no generic zero in a residue class, use ResidueClass.zero"+ (+) = lift2 Res.add+ (-) = lift2 Res.sub+ negate = lift1 Res.neg instance (Eq a, Integral.C a) => Ring.C (T a) where- one = error "no generic one in a residue class, use ResidueClass.one"- (*) = lift2 Res.mul- fromInteger = error "no generic integer in a residue class, use ResidueClass.fromInteger"+ one = error "no generic one in a residue class, use ResidueClass.one"+ (*) = lift2 Res.mul+ fromInteger = error "no generic integer in a residue class, use ResidueClass.fromInteger" x^n = Func.powerAssociative (*) (one (modulus x)) x n instance (Eq a, PID.C a) => Field.C (T a) where- (/) = lift2 Res.divide+ (/) = lift2 Res.divide recip = lift1 (flip Res.divide Ring.one)- fromRational' = error "no conversion from rational to residue class"+ fromRational' = error "no conversion from rational to residue class"
src/Number/ResidueClass/Func.hs view
@@ -64,20 +64,20 @@ Cons (\m -> (x m ==? y m) (eq m) (noteq m)) instance (Integral.C a) => Additive.C (T a) where- zero = zero- (+) = lift2 Res.add- (-) = lift2 Res.sub- negate = lift1 Res.neg+ zero = zero+ (+) = lift2 Res.add+ (-) = lift2 Res.sub+ negate = lift1 Res.neg instance (Integral.C a) => Ring.C (T a) where- one = one- (*) = lift2 Res.mul- fromInteger = Number.ResidueClass.Func.fromInteger+ one = one+ (*) = lift2 Res.mul+ fromInteger = Number.ResidueClass.Func.fromInteger instance (PID.C a) => Field.C (T a) where- (/) = lift2 Res.divide+ (/) = lift2 Res.divide recip = (NP.one /)- fromRational' = error "no conversion from rational to residue class"+ fromRational' = error "no conversion from rational to residue class" {-
src/Number/ResidueClass/Maybe.hs view
@@ -69,12 +69,12 @@ else error "ResidueClass.(==): Incompatible operands" instance (Eq a, Integral.C a) => Additive.C (T a) where- zero = Cons Nothing zero- (+) = lift2 Res.add (+)- (-) = lift2 Res.sub (-)- negate (Cons m r) = Cons m (negate r)+ zero = Cons Nothing zero+ (+) = lift2 Res.add (+)+ (-) = lift2 Res.sub (-)+ negate (Cons m r) = Cons m (negate r) instance (Eq a, Integral.C a) => Ring.C (T a) where- one = Cons Nothing one- (*) = lift2 Res.mul (*)- fromInteger = Cons Nothing . fromInteger+ one = Cons Nothing one+ (*) = lift2 Res.mul (*)+ fromInteger = Cons Nothing . fromInteger
src/Number/ResidueClass/Reader.hs view
@@ -11,7 +11,8 @@ import NumericPrelude.Base import NumericPrelude.Numeric -import Control.Monad (liftM2, liftM4)+import Control.Monad (liftM, liftM2, liftM4, ap)+import Control.Applicative (Applicative(pure, (<*>))) -- import Control.Monad.Reader (MonadReader) -- import qualified Prelude as P@@ -40,6 +41,13 @@ fromInteger :: (Integral.C a) => Integer -> T a a fromInteger = fromRepresentative . NP.fromInteger ++instance Functor (T a) where+ fmap = liftM++instance Applicative (T a) where+ (<*>) = ap+ pure = return instance Monad (T a) where (Cons x) >>= y = Cons (\r -> toFunc (y (x r)) r)
src/NumericPrelude/Base.hs view
@@ -3,11 +3,136 @@ to reexport items that we want from the standard Prelude. -} -module NumericPrelude.Base (module Prelude, ifThenElse, ) where-import Prelude hiding (- Int, Integer, Float, Double, Rational, Num(..), Real(..),- Integral(..), Fractional(..), Floating(..), RealFrac(..),- RealFloat(..), subtract, even, odd,- gcd, lcm, (^), (^^), sum, product,- fromIntegral, fromRational, )+module NumericPrelude.Base (+ (P.!!),+ (P.$),+ (P.$!),+ (P.&&),+ (P.++),+ (P..),+ (P.=<<),+ P.Bool(..),+ P.Bounded(..),+ P.Char,+ P.Either(..),+ P.Enum(..),+ P.Eq(..),+ P.FilePath,+ P.Functor(..),+ P.IO,+ P.IOError,+ P.Maybe(..),+ P.Monad(..),+ P.Ord(..),+ P.Ordering(..),+ P.Read(..),+ P.ReadS,+ P.Show(..),+ P.ShowS,+ P.String,+ P.all,+ P.and,+ P.any,+ P.appendFile,+ P.asTypeOf,+ P.break,+ P.concat,+ P.concatMap,+ P.const,+ P.curry,+ P.cycle,+ P.drop,+ P.dropWhile,+ P.either,+ P.elem,+ P.error,+ P.filter,+ P.flip,+ P.foldl,+ P.foldl1,+ P.foldr,+ P.foldr1,+ P.fst,+ P.getChar,+ P.getContents,+ P.getLine,+ P.head,+ P.id,+ P.init,+ P.interact,+ P.ioError,+ P.iterate,+ P.last,+ P.length,+ P.lex,+ P.lines,+ P.lookup,+ P.map,+ P.mapM,+ P.mapM_,+ P.maximum,+ P.maybe,+ P.minimum,+ P.not,+ P.notElem,+ P.null,+ P.or,+ P.otherwise,+ P.print,+ P.putChar,+ P.putStr,+ P.putStrLn,+ P.read,+ P.readFile,+ P.readIO,+ P.readLn,+ P.readParen,+ P.reads,+ P.realToFrac,+ P.repeat,+ P.replicate,+ P.reverse,+ P.scanl,+ P.scanl1,+ P.scanr,+ P.scanr1,+ P.seq,+ P.sequence,+ P.sequence_,+ P.showChar,+ P.showParen,+ P.showString,+ P.shows,+ P.snd,+ P.span,+ P.splitAt,+ P.tail,+ P.take,+ P.takeWhile,+ P.uncurry,+ P.undefined,+ P.unlines,+ P.until,+ P.unwords,+ P.unzip,+ P.unzip3,+ P.userError,+ P.words,+ P.writeFile,+ P.zip,+ P.zip3,+ P.zipWith,+ P.zipWith3,+ (P.||),++ catch,+ ifThenElse,+ ) where++import qualified System.IO.Error as IOError+import qualified Prelude as P+import Prelude (IO) import Data.Bool.HT (ifThenElse, )++catch :: IO a -> (P.IOError -> IO a) -> IO a+catch = IOError.catchIOError