packages feed

curry-base-0.2.8: Curry/ExtendedFlat/CurryArithmetics.hs

{-
  In Curry, Integers are encoded as binary values,
  being represented by constructor terms.

  (c) Holger Siegel 2009
-}
module Curry.ExtendedFlat.CurryArithmetics
    (CurryInt(..), CurryNat(..),
     trNat, trInt,
     toCurryInt, toIntExpression,
    ) where

import Curry.ExtendedFlat.Type


data CurryInt = Neg CurryNat | Zero | Pos CurryNat
data CurryNat = IHi | O CurryNat | I CurryNat


trNat :: Integral n =>
         a -> (a -> a) -> (a -> a) ->
         n -> a
trNat h o i = go
    where go n | n `mod` 2 == 0 = o (go m)
               | m == 0         = h
               | otherwise      = i (go m)
              where m = n `div` 2


trInt :: Integral n =>
         (nat -> t) -> t -> (nat -> t) ->
         nat -> (nat -> nat) -> (nat -> nat) ->
         n -> t
trInt n z p h o i = go
    where go x = case compare x 0 of
                   LT -> n (trNat h o i (negate x))
                   EQ -> z
                   GT -> p (trNat h o i x)


toCurryInt :: Integral a => a -> CurryInt
toCurryInt = trInt Neg Zero Pos IHi O I


toIntExpression :: Integral a => a -> Expr
toIntExpression = trInt neg_ zero_ pos_ iHi_ o_ i_


zero_, iHi_ :: Expr
pos_, neg_, o_, i_ :: Expr -> Expr

zero_  = prelCons tInt0 "Zero" []
pos_ n = prelCons tInt1 "Pos" [n]
neg_ n = prelCons tInt1 "Neg" [n]

iHi_ = prelCons tNat0 "IHi" []
o_ n = prelCons tNat1 "O" [n]
i_ n = prelCons tNat1 "I" [n]


tInt0, tInt1, tNat0, tNat1 :: TypeExpr
tInt0 = prelType "Int"
tInt1 = FuncType tInt0 tInt0

tNat0 = prelType "Nat"
tNat1 = FuncType tNat0 tNat0


prelType :: String -> TypeExpr
prelType s = TCons (mkQName ("Prelude", s)) []


prelCons :: TypeExpr -> String -> [Expr] -> Expr
prelCons t = Comb ConsCall . QName Nothing (Just t) "Prelude"