Modular arithmetic

Dylan Thurston dpt@math.harvard.edu
Tue, 21 Aug 2001 04:19:21 -0400


--KsGdsel6WgEHnImy
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Oops, forgot to attach the code.

--Dylan

--KsGdsel6WgEHnImy
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="TypeVal.hs"

-- TypeVal.hs: dependent types, here we come!
module TypeVal where

-- The functional dependency is necessary to get ghc to accept
-- some of the instances below.  Is this a bug?
class TypeVal a t | t -> a where
    -- typeToVal should ignore its argument.
    typeToVal :: t -> a

data Wrapper a = forall t . (TypeVal a t) => Wrapper t
instance Show a => Show (Wrapper a) where
   show x = "valToType " ++ show (getValue x)

class ValToType a where
    valToType :: a -> Wrapper a

getValue :: Wrapper a -> a
getValue (Wrapper p) = case p of {(_::t) -> typeToVal (undefined::t)}

-- Instances of ValToType for standard types.  This would also be a
-- straightforward compiler extension for the general case.
---- ValToType Bool
data TRUE = Dummy1
instance TypeVal Bool TRUE where typeToVal = const True
data FALSE = Dummy2
instance TypeVal Bool FALSE where typeToVal = const False

instance ValToType Bool where
    valToType True = Wrapper (undefined :: TRUE)
    valToType False = Wrapper (undefined :: FALSE)

---- ValToType Int, ValToType Integer
data Zero = Dummy3
instance TypeVal Integer Zero where typeToVal = const 0
data Succ n = Dummy4
instance (TypeVal Integer n) => TypeVal Integer (Succ n)
  where typeToVal = const (typeToVal (undefined :: n) + 1)
data Pred n = Dummy5
instance (TypeVal Integer n) => TypeVal Integer (Pred n)
  where typeToVal = const (typeToVal (undefined :: n) - 1)
data Dbl n = Dummy6
instance (TypeVal Integer n) => TypeVal Integer (Dbl n)
  where typeToVal = const (typeToVal (undefined :: n) * 2)

instance ValToType Integer where
    valToType n | n == 0 = Wrapper (undefined :: Zero)
	        | even n    =
		   case valToType (div n 2) of {Wrapper x ->
	           case x of {(_ :: t) ->
		   Wrapper (undefined :: Dbl t)}}
	        | n > 0  =
		   case valToType (n-1) of {Wrapper x ->
	           case x of {(_ :: t) ->
		   Wrapper (undefined :: Succ t)}}
	        | n < 1  =
		   case valToType (n+1) of {Wrapper x ->
	           case x of {(_ :: t) ->
		   Wrapper (undefined :: Pred t)}}

--- ValToType (a,b)
--- Doesn't work.  Perhaps a bug in ghc?
--- Don't need it yet, anyway.
--instance (TypeVal a1 t1, TypeVal a2 t2) => TypeVal (a1,a2) (t1,t2)
--    where typeToVal (x,y) = (typeToVal x, typeToVal y)

--instance (ValToType a, ValToType b) => ValToType (a,b) where
--    valToType (a,b) = case valToType a of {x ->
--		    case valToType b of {y ->
--		    Wrapper (x,y)}}

data NIL a = Dummy20
instance TypeVal [a] (NIL a)
  where typeToVal = const []
data CONS t r = Dummy21
instance (TypeVal [a] r, TypeVal a t) => TypeVal [a] (CONS t r)
  where typeToVal = const (typeToVal (undefined::t):typeToVal (undefined::r))

instance (ValToType a) => ValToType [a] where
  valToType [] = Wrapper (undefined::NIL a)
  valToType (x:xs) = case valToType x of {Wrapper x' ->
		     case x' of {(_::xt) ->
		     case valToType xs of {Wrapper xs' ->
		     case xs' of {(_::xst) ->
		     Wrapper (undefined::CONS xt xst)}}}}


--KsGdsel6WgEHnImy
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="Modulus.hs"

module Modulus where

import TypeVal

default (Integer)

data Mod s a = Mod {value::a} deriving (Eq, Show)

data Modulus a = forall s. TypeVal a s => Modulus (a -> Mod s a) (Mod s a -> a)

mkModulus :: (ValToType a, Integral a) => a -> Modulus a
mkModulus x = case valToType x of {Wrapper y ->
	      case y of {(_ :: t) ->
	      Modulus normalize (value :: Mod t a -> a)}}

normalize :: (TypeVal a s, Integral a) => a -> Mod s a
normalize x :: (Mod s a) = Mod (x `mod` typeToVal (undefined::s))

inModulus :: Modulus a -> (forall s . TypeVal a s =>  Mod s a -> Mod s a)
	        -> a -> a
inModulus (Modulus in_ out) f x = out (f (in_ x))

instance (TypeVal a s, Integral a) => Num (Mod s a) where
    Mod x + Mod y = normalize (x + y)
    Mod x - Mod y = normalize (x - y)
    negate (Mod x) = normalize (negate x)
    Mod x * Mod y = normalize (x * y)
    fromInteger a = normalize (fromInteger a)

--KsGdsel6WgEHnImy--