diff --git a/bsrc/Control/Monad.bs b/bsrc/Control/Monad.bs new file mode 100644 index 0000000..85d32ee --- /dev/null +++ b/bsrc/Control/Monad.bs @@ -0,0 +1,132 @@ +module Control.Monad + +import Data.Number + +export class Monad m { + (>>=)(left :: m a, right :: a -> m b) :: m b; + (>>)(left :: m a, right :: m b) :: m b = left >>= (\ _ -> right) + return(a :: a) :: m a; +} + +export restrict(Monad m) mapM(f :: a -> m b, ls :: [a]) :: m [b] +{ + case ls { + [] -> return([]); + (x:rest) -> return((:) `ap` f x `ap` mapM(f,rest)); + } +} + +export restrict(Monad m) mapM_(f :: a -> m b, ls :: [a]) :: m () +{ + case ls { + [] -> return (); + (x:rest) -> f(x) >> mapM_(f,rest); +} + +export restrict(Monad m) forM(ls :: [a], f :: a -> m b) :: m [b] = mapM(ls, f); +export restrict(Monad m) forM_(ls :: [a], f :: a -> m b) :: m () = mapM_(ls, f); + +export restrict(Monad m) sequence(lsM :: [m a]) :: m [a] +{ + case lsM { + [] -> return([]); + (x:rest) -> return((:) `ap` x `ap` sequence(rest)); +} + +export restrict(Monad m) sequence_(lsM :: [m a]) :: m () +{ + case lsM { + [] -> return(()); + (x:rest) -> x >> sequence(rest); +} + +export restrict(Monad m) +(=<<)(cont :: a -> m b, start :: m a) :: m b + = start >>= cont; + +export restrict(Monad m) +(>=>)(left :: a -> m b, right :: b -> m c, x :: a) :: m c +{ + step1 = left x + right step1 +} + +export restrict(Monad m) +(<=<)(right :: b -> m c, left :: a -> m b, x :: a) :: m c + = (>=>)(left,right,x) + +export restrict(Monad m) forever(action :: m a) :: m b + = action >> forever(action) + +export restrict(Monad m) void(action :: m a) :: m () = action >> return(()) + +export restrict(Monad m) join(actionM :: m (m a)) :: m a +{ + val = actionM; + return(val); +} + +export restrict(Monad m) filterM(f :: a -> m Bool, xs :: [a]) :: m [a] +{ + case xs { + [] -> return(()); + (x:rest) -> if f(x) + then return(x:) `ap` filterM(f,rest) + else filterM(f,rest); + } +} + +export restrict(Monad m) foldM(f :: a -> b -> m a, base :: a, xs :: [b]) :: m a +{ + case xs { + [] -> return(base); + (x:rest) -> { + newbase = f(base,x); + foldM(f,newbase,rest); + } +} + +export restrict(Monad m) foldM_(f :: a -> b -> m a, base :: a, xs :: [b]) ::m () +{ + case xs { + [] -> return(()); + (x:rest) -> { + newbase = f(base,x); + foldM_(f,newbase,rest); + } +} + +export restrict(Monad m, Unsigned u) +replicateM(count :: u, action :: m a) :: m [a] +{ + if count == 0 + then return([]) + else return( return((:)) `ap` action `ap` replicateM(count-1,action) ); +} + +export restrict(Monad m, Unsigned u) +replicateM_(count :: u, action :: m a) :: m () +{ + if count == 0 + then return(()) + else action >> replicateM_(count - 1, action); +} + +export restrict(Monad m) ap(mf :: m (a -> b), ma :: m a) :: m b +{ + func <- mf + a <- ma + return(func(a)); +} + +export restrict(Monad m) liftM(f :: a -> b, ma :: m a) :: m b + = return f `ap` ma +export restrict(Monad m) liftM2(f :: a -> b -> c, ma :: m a, mb :: m b) :: m c + = return f `ap` ma `ap` mb +export restrict(Monad m) liftM3(f :: a -> b -> c -> d, + ma :: m a, mb :: m b, mc :: m c) + = return f `ap` ma `ap` mb `ap` mc +export restrict(Monad m) liftM4(f :: a -> b -> c -> d -> e, + ma :: m a, mb :: m b, mc :: m c, md :: m d) + = return f `ap` ma `ap` mb `ap` mc + diff --git a/bsrc/Data/Bool.bs b/bsrc/Data/Bool.bs new file mode 100644 index 0000000..94984eb --- /dev/null +++ b/bsrc/Data/Bool.bs @@ -0,0 +1,11 @@ +module Data.Bool + +datatype Bool = True | False; + +export (&)(x :: Bool, y :: Bool) :: Bool = prim%and; +export (|)(x :: Bool, y :: Bool) :: Bool = prim%or; +export (^)(x :: Bool, y :: Bool) :: Bool = prim%xor; +export (not)(x :: Bool) :: Bool = prim%not; +export otherwise :: Bool = True; + + diff --git a/bsrc/Data/List.bs b/bsrc/Data/List.bs index 6a6b151..0a480fd 100644 --- a/bsrc/Data/List.bs +++ b/bsrc/Data/List.bs @@ -7,42 +7,49 @@ export datatype List a = export (++)(a :: [a], b :: [a]) :: [a] { - case a of - [] -> b - (af:ar) -> case b of - [] -> a - _ -> af:(ar ++ b) + case a { + [] -> b; + (af:ar) -> + case b { + [] -> a; + _ -> af:(ar ++ b); + } + } }; export null(ls :: [a]) :: Bool { - case ls of - [] -> True - _ -> False + case ls { + [] -> True; + _ -> False; + } }; export length(ls :: [a]) :: Int { - case ls of - [] -> 0 - _:rest -> length(rest) + case ls { + [] -> 0; + (_:rest) -> 1 + length(rest); + } }; export reverse(ls :: [a]) :: [a] { - helper(xs,acc) = { - case xs of - [] -> acc - (a:rest) -> helper(rest, (a:acc)) - } + let helper(xs,acc) = { + case xs { + [] -> acc; + (a:rest) -> helper(rest, (a:acc)); + } + }; helper(ls, []); }; export restrict(Eq a) find(f :: a -> Bool, ls :: [a]) :: Maybe a { - case ls of - [] -> False - (a:_) | f a -> a - (_:rest) -> find(f, rest) + case ls { + [] -> False; + (a:_) | f(a) -> a; + (_:rest) -> find(f, rest); + } }; diff --git a/bsrc/Data/Number.bs b/bsrc/Data/Number.bs new file mode 100644 index 0000000..d0e96c9 --- /dev/null +++ b/bsrc/Data/Number.bs @@ -0,0 +1,93 @@ +module Data.Number + +import Data.Object + +export restrict(Eq a) Num a { + (+)(x :: a, y :: a) :: a; + (*)(x :: a, y :: a) :: a; + (-)(x :: a, y :: a) :: a; +}; + +export restrict(Num a) Signed a { + negate(x :: a) :: a; + abs(x :: a) :: a; + signum(x :: a) :: a; +}; + +export restrict(Num a) Unsigned a { +}; + +export class Bounded a { + minBound :: a; + maxBound :: a; +}; + +export datatype Ordering = Before | Equal | After; + +export class restrict(Eq a) Ord a { + compare(_ :: a, _ :: a) :: Ordering; + + (<)(x :: a, y :: b) :: Bool + { + case compare(x,y) { + Before -> True; + _ -> False; + } + } + + (>)(x :: a, y :: b) :: Bool + { + case compare(x,y) { + After -> True; + _ -> False; + } + } + + (<=)(x :: a, y :: b) :: Bool + { + case compare(x,y) { + After -> False; + _ -> True; + } + } + + (>=)(x :: a, y :: b) :: Bool + { + case compare(x,y) { + Before -> False; + _ -> True; + } + } + + max(x :: a, y :: b) :: a + { + case compare(x,y) { + Before -> y; + _ -> x; + } + } + + min(x :: a, y :: b) :: b + { + case compare(x,y) { + After -> y; + _ -> x; + } +} + +export class Enum a { + succ(a) :: a; + pred(a) :: a; + toEnum(Integer) :: a; + fromEnum(a) :: Integer; + enumFromTo(a, a) :: [a]; + enumFromThenTo(a, a, a) :: [a]; +} + +export restrict(Ord a, Num a) +createEnum(s :: a, e :: a, m :: a) :: [a] = s : createEnum(s + m, e, m); + +export restrict(Ord a, Num a) +diff(x :: a, y :: a) :: a = if x > y then x - y else y - x; + + diff --git a/bsrc/Data/Number/Machine.bs b/bsrc/Data/Number/Machine.bs new file mode 100644 index 0000000..05fdb82 --- /dev/null +++ b/bsrc/Data/Number/Machine.bs @@ -0,0 +1,106 @@ +module Data.Number.Machine + +type Int = prim%Int; +type Word = prim%Word; + +export instance Eq Int { + (==)(x,y) = prim%inteq(x,y); + (/=)(x,y) = prim%intneq(x,y); +} + +export instance Eq Word { + (==)(x,y) = prim%wordeq(x,y); + (/=)(x,y) = prim%wordneq(x,y); +} + +export instance Num Int { + (+)(x,y) = prim%intplus(x,y); + (-)(x,y) = prim%intminus(x,y); + (*)(x,y) = prim%intmult(x,y); +} + +export instance Num Word { + (+)(x,y) = prim%wordplus(x,y); + (-)(x,y) = prim%wordminus(x,y); + (*)(x,y) = prim%wordmult(x,y); +} + +export instance Signed Int { + negate = prim%intnegate; + abs = prim%intabs; + signum(x) = case x { + _ | x < 0 -> -1; + | x == 0 -> 0; + | otherwise -> 1; + } +} + +export instance Unsigned Word; + +export instance Bounded Int { + minBound = prim%intminbound; + maxBound = prim%intmaxbound; +} + +export instance Bounded Word { + minBound = 0; + maxBound = prim%wordmaxbound; +} + +export instance Ord Int { + compare(x,y) = if x == y + then Equal + else if x < y + then Before + else After + (<) = prim%intlt + (<=) = prim%intlte + (>) = prim%intgt + (>=) = prim%intgte + max(x,y) = if x > y then x else y; + min(x,y) = if x < y then x else y; +} + +export instance Ord Word { + compare(x,y) = if x == y + then Equal + else if x < y + then Before + else After + (<) = prim%wordlt + (<=) = prim%wordlte + (>) = prim%wordgt + (>=) = prim%wordgte + max(x,y) = if x > y then x else y; + min(x,y) = if x < y then x else y; +} + +export instance Enum Int { + succ(x) = x + 1; + pred(x) = x - 1; + toEnum(x) = if x > safeConvert(maxBound :: Int) + then maxBound + else if x < safeConvert(minBound :: Int) + then minBound + else unsafeConvert(x) + fromEnum(x) = safeConvert(x) + enumFromTo(x,y) = if x > y then createEnum(x,y,-1) else createEnum(x,y,1); + enumFromThenTo(x,y) = let direction = if x > y then -1 else 1 + amt = diff x y + in createEnum(x,y,amt * direction) +} + +export instance Enum Word { + succ(x) = x + 1; + pred(x) = x - 1; + toEnum(x) = if x > safeConvert(maxBound :: Word) + then maxBound + else if x < safeConvert(minBound :: Word) + then minBound + else unsafeConvert(x) + fromEnum(x) = safeConvert(x) + enumFromTo(x,y) = if x > y then createEnum(x,y,-1) else createEnum(x,y,1); + enumFromThenTo(x,y) = let direction = if x > y then -1 else 1 + amt = diff x y + in createEnum(x,y,amt * direction) +} diff --git a/bsrc/Data/Object.bs b/bsrc/Data/Object.bs new file mode 100644 index 0000000..8f24a26 --- /dev/null +++ b/bsrc/Data/Object.bs @@ -0,0 +1,27 @@ +module Data.Object + +import Data.Bool; + +export eq(x :: a, y :: a) :: Bool = prim%eq(x,y); + +class Eq a { + (==)(x :: a, y :: a) :: Bool = not (x /= y); + (/=)(x :: a, y :: a) :: Bool = not (x == y); +} + +instance Eq () { + (==)(x,y) = True; + (/=)(x,y) = False; +} + +instance Eq Bool { + (/=)(x,y) = x ^ y; +} + +class SafelyConvertable a b { + safeConvert :: a -> b; +} + +class UnsafelyConvertable a b { + unsafeConvert :: a -> b; +}