Zuletzt geändert: So, 23.04.2006

«K12/K13» Z.hs «PDF», «POD»



Download
module Z (Z(..), zero, one, negate) where

import Base
import N (N, n02n, n2n0)
import qualified N (one)
import qualified N0 (zero)

data Z = Zero | Pos N | Neg N deriving (Eq)
zero = Zero
one  = Pos N.one

instance Show Z where
  show a = "Z[" ++ (show . toInteger $ a) ++ "]"

n02z n | n == N0.zero = Zero
n02z n | otherwise    = Pos $ n02n n

abs' (Pos a) = a
abs' (Neg a) = a

instance Num Z where
  a + b | a == negate b                           = Zero
  a + b | a == Zero                               = b
  a + b | a >  Zero && b >= Zero                  = Pos $ abs' a + abs' b
  a + b | a >  Zero && b <  Zero && abs a > abs b = Pos $ abs' a - abs' b
  a + b | a >  Zero && b <  Zero && abs a < abs b = Neg $ abs' b - abs' a
  a + b | a <  Zero && b <= Zero                  = Neg $ abs' a + abs' b
  a + b | a <  Zero && b >  Zero && abs a > abs b = Neg $ abs' a - abs' b
  a + b | a <  Zero && b >  Zero && abs a < abs b = Pos $ abs' b - abs' a

  a - b = a + negate b

  Zero * _ = Zero
  _ * Zero = Zero
  a * b = s (abs' a * abs' b) where
    s x | a >= Zero && b >= Zero = Pos x
    s x | a <= Zero && b <= Zero = Pos x
    s x | otherwise              = Neg x

  abs Zero    = Zero
  abs (Pos n) = Pos n
  abs (Neg n) = Pos n

  negate Zero    = Zero
  negate (Pos n) = Neg n
  negate (Neg n) = Pos n

  signum Zero    = Zero
  signum (Pos _) =  one
  signum (Neg _) = -one

  fromInteger 0 = Zero
  fromInteger n | n > 0 = Pos $ fromInteger n
  fromInteger n | n < 0 = Neg $ fromInteger (-n)

instance Real Z where
  toRational = toRational . toInteger

instance Enum Z where
  succ a = a + 1
  pred a = a - 1

  toEnum   = fromInteger . fromIntegral
  fromEnum = fromIntegral . toInteger

instance Integral Z where
  a `div` Zero = error "Division by Z[0]!"
  a `div` b = s (abs' a `div` abs' b) where
    s x | a >= Zero && b >= Zero = Pos x
    s x | a <= Zero && b <= Zero = Pos x
    s x | otherwise              = Neg x

  toInteger Zero    = 0
  toInteger (Pos a) =  toInteger a
  toInteger (Neg a) = -toInteger a

instance Ord Z where
  a       <= b | a == b = True
  (Pos _) <= Zero       = False
  (Neg _) <= Zero       = True
  Zero    <= Zero       = True
  Zero    <= (Pos _)    = True
  Zero    <= (Neg _)    = False
  a       <= b          = a <= (b - one)