```-- | Integers augmented with Infinity.
module Util.IntPlus(
IntPlus,
infinity
) where

-- --------------------------------------------------------------------
-- The datatype
-- --------------------------------------------------------------------

-- | The Bool is a sign, with True meaning positive infinity.
data IntPlus = Infinite Bool | Finite Integer deriving Eq

-- --------------------------------------------------------------------
-- The interface
-- --------------------------------------------------------------------

infinity :: IntPlus
infinity = Infinite True

instance Ord IntPlus where
compare i1 i2 = case (i1,i2) of
(Infinite b1,Infinite b2) -> compare b1 b2
(Finite _,Infinite b) -> if b then LT else GT
(Infinite b,Finite _) -> if b then GT else LT
(Finite i1,Finite i2) -> compare i1 i2

instance Show IntPlus where
showsPrec _ (Infinite b) s = if b then "infinity"++s else "-infinity"++s
showsPrec p (Finite i) s = showsPrec p i s

instance Num IntPlus where
(+) i1 i2 = case (i1,i2) of
(Finite i1,Finite i2) -> Finite (i1 + i2)
(Infinite b,Finite _) -> Infinite b
(Finite _,Infinite b) -> Infinite b
(Infinite b1,Infinite b2) ->
if b1 == b2 then Infinite b1 else
error "IntPlus: attempt to subtract infinities of like sign"
(*) i1 i2 = case (i1,i2) of
(Finite i1,Finite i2) -> Finite (i1*i2)
(Finite i,Infinite b) -> mul i b
(Infinite b,Finite i) -> mul i b
(Infinite b1,Infinite b2) -> Infinite (b1 == b2)
where
mul i b = case compare i 0 of
LT -> Infinite (not b)
EQ -> Finite 0
GT -> Infinite b

negate (Finite i) = Finite (negate i)
negate (Infinite b) = Infinite (not b)

abs (Finite i) = Finite (abs i)
abs (Infinite _) = infinity

signum i = case compare i 0 of
LT -> -1
EQ -> 0
GT -> 1

fromInteger i = Finite i

```