shithub: MicroHs

ref: b4a7a0d4c04ad0fb96d0b279d35da2658d58a0e1
dir: /lib/Data/Enum.hs/

View raw version
module Data.Enum(module Data.Enum) where
import Prelude()              -- do not import Prelude
import Primitives
import Control.Error
import Data.Bool
import Data.Char_Type
import Data.Bounded
import Data.Function
import Data.Int
import Data.List
import Data.Num
import Data.Ord

class Enum a where
  succ           :: a -> a
  pred           :: a -> a
  toEnum         :: Int -> a
  fromEnum       :: a -> Int

  enumFrom       :: a -> [a]
  enumFromThen   :: a -> a -> [a]
  enumFromTo     :: a -> a -> [a]
  enumFromThenTo :: a -> a -> a -> [a]

  succ                   = toEnum . (+ 1) . fromEnum
  pred                   = toEnum . (subtract 1) . fromEnum
  enumFrom x             = map toEnum [fromEnum x ..]
  enumFromThen x y       = map toEnum [fromEnum x, fromEnum y ..]
  enumFromTo x y         = map toEnum [fromEnum x .. fromEnum y]
  enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]

boundedEnumFrom :: forall a . (Enum a, Bounded a) => a -> [a]
boundedEnumFrom n = map toEnum [fromEnum n .. fromEnum (maxBound `asTypeOf` n)]

boundedEnumFromThen :: forall a . (Enum a, Bounded a) => a -> a -> [a]
boundedEnumFromThen n1 n2
  | i_n2 >= i_n1  = map toEnum [i_n1, i_n2 .. fromEnum (maxBound `asTypeOf` n1)]
  | otherwise     = map toEnum [i_n1, i_n2 .. fromEnum (minBound `asTypeOf` n1)]
  where
    i_n1 = fromEnum n1
    i_n2 = fromEnum n2

numericEnumFrom :: (Num a) => a -> [a]
numericEnumFrom n = n : numericEnumFrom (n + 1)

numericEnumFromThen :: (Num a) => a -> a -> [a]
numericEnumFromThen n m = from n
  where
    d = m - n
    from i = i : from (i + d)

numericEnumFromTo :: (Num a, Ord a) => a -> a -> [a]
numericEnumFromTo l h = takeWhile (<= h) (numericEnumFrom l)

numericEnumFromThenTo :: (Num a, Ord a) => a -> a -> a -> [a]
numericEnumFromThenTo l m h =
    if m > l then
      takeWhile (<= h) (numericEnumFromThen l m)
    else
      takeWhile (>= h) (numericEnumFromThen l m)

-- This instance is difficult to put in Data.Int,
-- so it gets to live here.
instance Enum Int where
  succ x = x + 1
  pred x = x - 1
  toEnum x = x
  fromEnum x = x
  enumFrom = numericEnumFrom
  enumFromThen = numericEnumFromThen
  enumFromTo = numericEnumFromTo
  enumFromThenTo = numericEnumFromThenTo

-- Likewise for Bool
instance Enum Bool where
  fromEnum False = 0
  fromEnum True  = 1
  toEnum i = if primIntEQ i (0::Int) then False else
             if primIntEQ i (1::Int) then True  else
             error "Enum.Bool.toEnum: bad arg"

instance Enum Char where
  fromEnum = primOrd
  toEnum   = primChr


instance Enum Ordering where
  fromEnum LT = (0::Int)
  fromEnum EQ = (1::Int)
  fromEnum GT = (2::Int)
  toEnum i =      if i `primIntEQ` 0 then LT
             else if i `primIntEQ` 1 then EQ
             else if i `primIntEQ` 2 then GT
             else error "Ord.toEnum: out of range"