ddc-code 0.4.2.1 → 0.4.3.1
raw patch · 27 files changed
+1638/−546 lines, 27 filesdep ~base
Dependency ranges changed: base
Files
- LICENSE +1/−1
- ddc-code.cabal +19/−2
- salt/runtime64/debug/Trace.dcs +37/−37
- sea/primitive/Primitive.c +5/−0
- sea/primitive/Primitive.h +4/−3
- tetra/base/Class/Applicative.ds +61/−0
- tetra/base/Class/Functor.ds +19/−0
- tetra/base/Class/Monad.ds +54/−0
- tetra/base/Class/Ord.ds +14/−0
- tetra/base/Class/Show.ds +48/−0
- tetra/base/Control/Parsec.ds +166/−0
- tetra/base/Data/Array.ds +7/−1
- tetra/base/Data/Function.ds +2/−2
- tetra/base/Data/List.ds +129/−57
- tetra/base/Data/Map.ds +325/−0
- tetra/base/Data/Maybe.ds +60/−2
- tetra/base/Data/Numeric/Bool.ds +5/−4
- tetra/base/Data/Numeric/Nat.ds +20/−5
- tetra/base/Data/Numeric/Word.ds +9/−0
- tetra/base/Data/Stream.ds +125/−112
- tetra/base/Data/Text.ds +4/−306
- tetra/base/Data/Text/Base.ds +244/−0
- tetra/base/Data/Text/Char.ds +28/−0
- tetra/base/Data/Text/List.ds +66/−0
- tetra/base/Data/Text/Operator.ds +54/−0
- tetra/base/Data/Text/Show.ds +119/−0
- tetra/base/Math/Combinations.ds +13/−14
LICENSE view
@@ -1,7 +1,7 @@ -------------------------------------------------------------------------------- The Disciplined Disciple Compiler License (MIT style) -Copyrite (K) 2007-2014 The Disciplined Disciple Compiler Strike Force+Copyrite (K) 2007-2016 The Disciplined Disciple Compiler Strike Force All rights reversed. Permission is hereby granted, free of charge, to any person obtaining a copy
ddc-code.cabal view
@@ -1,5 +1,5 @@ Name: ddc-code-Version: 0.4.2.1+Version: 0.4.3.1 License: MIT License-file: LICENSE Author: The Disciplined Disciple Compiler Strike Force@@ -28,11 +28,28 @@ sea/primitive/Primitive.h sea/runtime/Runtime.h + tetra/base/Class/Applicative.ds+ tetra/base/Class/Functor.ds+ tetra/base/Class/Monad.ds+ tetra/base/Class/Ord.ds+ tetra/base/Class/Show.ds++ tetra/base/Control/Parsec.ds+ tetra/base/Data/Numeric/Bool.ds tetra/base/Data/Numeric/Nat.ds+ tetra/base/Data/Numeric/Word.ds++ tetra/base/data/Text/Base.ds+ tetra/base/data/Text/Char.ds+ tetra/base/data/Text/List.ds+ tetra/base/data/Text/Operator.ds+ tetra/base/data/Text/Show.ds+ tetra/base/Data/Array.ds tetra/base/Data/Function.ds tetra/base/Data/List.ds+ tetra/base/Data/Map.ds tetra/base/Data/Maybe.ds tetra/base/Data/Ref.ds tetra/base/Data/Stream.ds@@ -46,7 +63,7 @@ Library build-depends:- base >= 4.6 && < 4.9,+ base >= 4.6 && < 4.10, filepath >= 1.3 && < 1.5 exposed-modules:
salt/runtime64/debug/Trace.dcs view
@@ -65,7 +65,7 @@ -- Some format that we don't handle yet, -- or the header is trashed.- _ -> do primPutString "Unknown\n"+ _ -> do primPutString "Unknown\n"# 0# @@ -78,17 +78,17 @@ format = band# header 0x0fw32# tag = shr# header 8w32# - primPutString "Thunk\n"- fieldAddr "{ ptr = " (takePtr# obj)- fieldWord32 " format = " format- fieldWord32 " tag = " tag- fieldNat " params = " (paramsThunk obj)- fieldNat " boxes = " (boxesThunk obj)- fieldNat " args = " (argsThunk obj)- fieldNat " runs = " (runsThunk obj)- fieldAddr " fun = " (funThunk obj)+ primPutString "Thunk\n"#+ fieldAddr "{ ptr = "# (takePtr# obj)+ fieldWord32 " format = "# format+ fieldWord32 " tag = "# tag+ fieldNat " params = "# (paramsThunk obj)+ fieldNat " boxes = "# (boxesThunk obj)+ fieldNat " args = "# (argsThunk obj)+ fieldNat " runs = "# (runsThunk obj)+ fieldAddr " fun = "# (funThunk obj) traceThunkPtrs obj 0#- primPutString "}\n"+ primPutString "}\n"# case trace of True# -> traceThunkPtrss obj 0#@@ -104,11 +104,11 @@ False# -> do addr = takePtr# (getThunk obj i)- primPutString " arg "+ primPutString " arg "# primPutString (primShowNat i)- primPutString " = "+ primPutString " = "# primPutString (primShowAddr addr)- primPutString ";\n"+ primPutString ";\n"# traceThunkPtrs obj (add# i 1#) @@ -134,13 +134,13 @@ tag = shr# header 8w32# arity = peek# ptr 4# - primPutString "Boxed\n"- fieldAddr "{ ptr = " (takePtr# obj)- fieldWord32 " format = " format- fieldWord32 " tag = " tag- fieldNat " arity = " (promote# arity)+ primPutString "Boxed\n"#+ fieldAddr "{ ptr = "# (takePtr# obj)+ fieldWord32 " format = "# format+ fieldWord32 " tag = "# tag+ fieldNat " arity = "# (promote# arity) traceBoxedPtrs obj (promote# arity) 0#- primPutString "}\n"+ primPutString "}\n"# case trace of True# -> traceBoxedPtrss obj (promote# arity) 0#@@ -156,11 +156,11 @@ False# -> do addr = takePtr# (getBoxed obj i) - primPutString " arg "+ primPutString " arg "# primPutString (primShowNat i)- primPutString " = "+ primPutString " = "# primPutString (primShowAddr addr)- primPutString ";\n"+ primPutString ";\n"# traceBoxedPtrs obj n (add# i 1#) @@ -185,12 +185,12 @@ tag = shr# header 8w32# size = peek# ptr 4# - primPutString "Raw\n"- fieldAddr "{ ptr = " (takePtr# obj)- fieldWord32 " format = " format- fieldWord32 " tag = " tag- fieldWord32 " size = " size- primPutString "}\n"+ primPutString "Raw\n"#+ fieldAddr "{ ptr = "# (takePtr# obj)+ fieldWord32 " format = "# format+ fieldWord32 " tag = "# tag+ fieldWord32 " size = "# size+ primPutString "}\n"# 0# @@ -203,11 +203,11 @@ format = band# header 0x0fw32# size = shr# 4w32# (band# header 0xf0w32#) - primPutString "Small\n"- fieldAddr "{ ptr = " (takePtr# obj)- fieldWord32 " format = " format- fieldWord32 " size = " size- primPutString "}\n"+ primPutString "Small\n"#+ fieldAddr "{ ptr = "# (takePtr# obj)+ fieldWord32 " format = "# format+ fieldWord32 " size = "# size+ primPutString "}\n"# 0# @@ -216,20 +216,20 @@ fieldAddr (name: TextLit#) (val: Addr#): Void# = do primPutString name primPutString (primShowAddr val)- primPutString ";\n"+ primPutString ";\n"# -- | Print a Nat# field to stdout. fieldNat (name: TextLit#) (val: Nat#): Void# = do primPutString name primPutString (primShowNat val)- primPutString ";\n"+ primPutString ";\n"# -- | Print a Word32# field to stdout. fieldWord32 (name: TextLit#) (val: Word32#): Void# = do primPutString name primPutString (primShowWord32 val)- primPutString ";\n"+ primPutString ";\n"#
sea/primitive/Primitive.c view
@@ -80,6 +80,11 @@ } +// Print a text literal to stdout.+void primPutTextLit (string_t* str)+{ fputs(str, stdout);+}+ // Print a text vector to stdout. void primPutVector (Obj* obj) { string_t* str = (string_t*) _payloadRaw(obj);
sea/primitive/Primitive.h view
@@ -113,7 +113,8 @@ // Other primitives ----------------------------------------------------------- // These are defined in C land and linked into the runtime library.-extern string_t* primShowInt (int i);-extern string_t* primShowNat (nat_t i);-extern void primPutString (string_t* str);+extern string_t* primShowInt (int i);+extern string_t* primShowNat (nat_t i);+extern void primPutTextLit (string_t* str);+extern void primPutString (string_t* str);
+ tetra/base/Class/Applicative.ds view
@@ -0,0 +1,61 @@++module Class.Applicative+export +{ dFunctorOfApplicative;+ pure; ap;+ liftA; liftA2; liftA3+}+import Class.Functor+where+++-- A functor with application.+data Applicative (f: Data -> Data) where+ Applicative+ : Functor f + -> ([a: Data]. a -> f a) -- pure+ -> ([a b: Data]. f (a -> b) -> f a -> f b) -- ap+ -> Applicative f+++-- | Take the Functor dictionary from an Applicative dictionary.+dFunctorOfApplicative + : [f: Data -> Data]+ . Applicative f -> Functor f++dFunctorOfApplicative (Applicative dFunctor _ _)+ = dFunctor+++-- | Return a value in the carrier.+pure : [f: Data -> Data]. [a: Data]+ . Applicative f -> a -> f a++pure (Applicative _ pure' _) x+ = pure' x+++-- | Apply a function in the carrier its argument in another carrier.+ap : [f: Data -> Data]. [a b: Data]+ . Applicative f -> f (a -> b) -> f a -> f b++ap (Applicative _ _ ap') xfab xfa+ = ap' xfab xfa+++-- Lifting functions.+liftA (dapp: Applicative f) (f: a -> b) (xa: f a): f b+ = ap dapp (pure dapp f) xa+++liftA2 (dapp: Applicative f)+ (f: a -> b -> c) (xa: f a) (xb: f b): f c+ = let dfun = dFunctorOfApplicative dapp+ in ap dapp (fmap dfun f xa) xb+++liftA3 (dapp: Applicative f) + (f: a -> b -> c -> d) (xa: f a) (xb: f b) (xc: f c): f d+ = let dfun = dFunctorOfApplicative dapp+ in ap dapp (ap dapp (fmap dfun f xa) xb) xc+
+ tetra/base/Class/Functor.ds view
@@ -0,0 +1,19 @@++module Class.Functor +export fmap+where+++-- | Class of collection types that can be mapped over.+data Functor (f: Data -> Data) where+ Functor+ : ([a b: Data]. (a -> b) -> f a -> f b) -- fmap+ -> Functor f+++-- | Apply a function to values of type 'a' in the input collection.+fmap : [f: Data -> Data]. [a b: Data]+ . Functor f -> (a -> b) -> f a -> f b++fmap (Functor fmap') = fmap'+
+ tetra/base/Class/Monad.ds view
@@ -0,0 +1,54 @@++module Class.Monad+export +{ dFunctorOfMonad; dApplicativeOfMonad;+ return; bind+}+import Class.Functor+import Class.Applicative+where+++-- | Class of types that support associative sequencing.+data Monad (m: Data -> Data) where+ Monad+ : Applicative m+ -> ([a: Data]. a -> m a) -- return+ -> ([a b: Data]. m a -> (a -> m b) -> m b) -- bind+ -> Monad m+++-- | Take the Functor dictionary from a Monad dictionary.+dFunctorOfMonad + : [m: Data -> Data]+ . Monad m -> Functor m++dFunctorOfMonad dMonad+ = dFunctorOfApplicative (dApplicativeOfMonad dMonad)+++-- | Take the Applicative dictionary from a Monad dictionary.+dApplicativeOfMonad+ : [m: Data -> Data]+ . Monad m -> Applicative m++dApplicativeOfMonad (Monad dApplicative _ _)+ = dApplicative+++-- | Return a value in a monad.+return : [m: Data -> Data]. [a: Data]+ . Monad m -> a -> m a++return (Monad _ return' _) x+ = return' x+++-- | Evaluate a monadic compuation and pass the result to +-- a function that produces a new monadic computation.+bind : [m: Data -> Data]. [a b: Data]+ . Monad m -> m a -> (a -> m b) -> m b++bind (Monad _ _ bind') ma mf + = bind' ma mf+
+ tetra/base/Class/Ord.ds view
@@ -0,0 +1,14 @@++module Class.Ord+where+++data Ordering where+ LT : Ordering+ GT : Ordering+ EQ : Ordering+++data Ord (k: Data) where+ Ord : (k -> k -> Ordering) -> Ord k+
+ tetra/base/Class/Show.ds view
@@ -0,0 +1,48 @@++module Class.Show+export+{ show; show_bool; show_nat;+ show_text;+ show_tup2;+ show_list;+}+import Data.Text+import Data.List+where+++-- | Class dictionary for Show.+data Show (a: Data) where+ Show : (a -> Text) -> Show a++show ((Show sh): Show a) (x: a): Text+ = sh x+++-------------------------------------------------------------------------------+-- Instances for basic types.+-- We define these in this module to avoid making it recursive+-- with the modules that define basic data types.+show_bool = Show showBool+show_nat = Show showNat+++-- ISSUE: #381: Escape non-printable characters in base Show library.+show_text: Show Text+ = Show sh+ where sh tx = "\"" % tx % "\""+++show_tup2 ((Show sh_a): Show a) ((Show sh_b): Show b)+ : Show (Tup2 a b)+ = Show sh+ where + sh (T2 x y) = parens $ "T2" %% sh_a x %% sh_b y+++show_list ((Show sh_a): Show a): Show (List a)+ = Show sh+ where + sh Nil = "Nil"+ sh (Cons x xs) = parens $ "Cons" %% sh_a x %% sh xs+
+ tetra/base/Control/Parsec.ds view
@@ -0,0 +1,166 @@++module Control.Parsec+export +{ parse; zero; item; satisfies;+ from; alt;+ monad_Parser;+ some; many;+}+import Class.Monad+import Data.List+import Data.Tuple+import Data.Maybe+where++data Parser (t a: Data) where+ Parser: (List t → List (Tup2 a (List t))) → Parser t a+++-- | Apply a parser to a list of input tokens.+parse ((Parser p): Parser t a) (ts: List t): List (Tup2 a (List t))+ = p ts+++-- Functor --------------------------------------------------------------------+functor_Parser [t: Data]: Functor (Parser t)+ = Functor parser_fmap++ where parser_fmap [t a b: Data] (f: a → b) (parserA: Parser t a): Parser t b+ = Parser $ λts+ → for (parse parserA ts) $ λ(T2 resultA ts2)+ → T2 (f resultA) ts2+++-- Applicative ----------------------------------------------------------------+applicative_Parser [t: Data]: Applicative (Parser t)+ = Applicative + functor_Parser+ parser_pure+ parser_ap++ where parser_pure (x: a): Parser t' a+ = Parser $ λts → Cons (T2 x ts) Nil++ parser_ap (parserF: Parser t' (a → b))+ (parserA: Parser t' a)+ : Parser t' b+ = Parser $ λts → concat+ $ for (parse parserF ts) $ λ(T2 resultF ts2)+ → for (parse parserA ts2) $ λ(T2 resultA ts3)+ → T2 (resultF resultA) ts3+++-- Monad ----------------------------------------------------------------------+monad_Parser [t: Data]: Monad (Parser t)+ = Monad applicative_Parser+ parser_return+ parser_bind++ where parser_return (x: a): Parser t' a+ = Parser $ λts → Cons (T2 x ts) Nil++ parser_bind+ (parserA: Parser t' a)+ (mkParserB: a → Parser t' b)+ : Parser t' b+ = Parser $ λts → concat + $ for (parse parserA ts) $ λ(T2 resultA ts2)+ → for (parse (mkParserB resultA) ts2) $ λ(T2 resultB ts3)+ → T2 resultB ts3+++-------------------------------------------------------------------------------+-- | Always fail, producing no possible parses.+zero: Parser t a+ = Parser $ λ_ → Nil+++-- | Consume the first input token, failing if there aren't any.+item: Parser t t+ = Parser $ λts+ → case ts of+ Nil → Nil+ Cons t ts' → Cons (T2 t ts) Nil+++-- | A parser that accepts a single token that satisfies the given predicate,+-- producing the given value if it matches.+satisfies (pred: t → Bool): Parser t t+ = Parser $ λts+ → case ts of+ Nil → Nil+ Cons t ts+ | pred t → Cons (T2 t ts) Nil+ | otherwise → Nil+++-- | Use the given function to check whether to accept the next token,+-- returning the result that it produces.+from (accept: t → Maybe a): Parser t a+ = Parser $ λts+ → case ts of+ Nil → Nil+ Cons t ts'+ → case accept t of+ Nothing → Nil+ Just x → Cons (T2 x ts') Nil+++-- | Combine two argument parsers, producing a new one that accepts+-- strings parsed by either of the argument parsers.+plus (parserA parserB: Parser t a): Parser t a+ = Parser $ λts + → append (parse parserA ts) (parse parserB ts)+++-- | Combine two argument parsers, producing a new one that accepts+-- strings parser by either of the argument parser, but not both.+-- We prefer result produced by the first parser over the second.+alt (parserA parserB: Parser t a): Parser t a+ = Parser $ λts+ → case parse parserA ts of+ Nil → parse parserB ts+ res → res+++-- | Combine a list of argument parsers, producing a new one that+-- gives the result produced by the first matching argument parser.+alts (parsers: List (Parser t a)): Parser t a+ = case parsers of+ Nil → zero+ Cons p ps → alt p (alts ps)+++-- | Like `alts`, accept use the given default parser if no +-- parser from the first list succeeds.+altss (parsers: List (Parser t a)) (def: Parser t a): Parser t a+ = case parsers of+ Nil → def+ Cons p ps → alt p (altss ps def)+++-- | Apply a parser followed by another parser,+-- producing a tuple that contains both results.+follows (parserA: Parser t a) (parserB: Parser t b): Parser t (Tup2 a b)+ = Parser $ λts → concat+ $ for (parse parserA ts) $ λ(T2 resultA ts2)+ → for (parse parserB ts2) $ λ(T2 resultB ts3)+ → T2 (T2 resultA resultB) ts3+++-- | Parse zero or more things, yielding a list of those things.+some (parserA: Parser t a): Parser t (List a)+ = alt (bind monad_Parser parserA $ λx → + bind monad_Parser (some parserA) $ λxs →+ return monad_Parser (Cons x xs))+ (return monad_Parser Nil)+++-- | Parse one or more things, yielding a list of those things.+many [a t: Data] (parserA: Parser t a): Parser t (List a)+ = alt (bind monad_Parser parserA $ λx →+ bind monad_Parser (some parserA) $ λxs →+ return monad_Parser (Cons x xs))+ (bind monad_Parser parserA $ λx →+ return monad_Parser (Cons x Nil))+
tetra/base/Data/Array.ds view
@@ -1,11 +1,17 @@ module Data.Array-export { allocArray; readArray; writeArray }+export { allocArray; readArray; writeArray; }+import Data.Numeric.Nat import foreign boxed type Array : Region ~> Data ~> Data import foreign c value+ -- ISSUE #377: Use type equations during Tetra to Salt transform.+ -- The Tetra to Salt transform isn't looking through type equations,+ -- so types of primitives that use type synonyms break. Eg if we use+ -- 'Nat' here instead of 'Nat#' the transform won't know these primtives+ -- accept unboxed values. allocArray : [r: Region]. [a: Data]. Nat# -> a -> S (Alloc r) (Array r a) readArray : [r: Region]. [a: Data]. Array r a -> Nat# -> S (Read r) a writeArray : [r: Region]. [a: Data]. Array r a -> Nat# -> a -> S (Write r) Void#
tetra/base/Data/Function.ds view
@@ -1,6 +1,6 @@ module Data.Function-export { id; apply; compose }+export { id; apply; compose; } where @@ -18,5 +18,5 @@ -- | Compose two functions. -- The operator '∘' is desugared to applications of this function. compose [a b c: Data] (f: b -> c) (g: a -> b): a -> c- = λx : a. f (g x)+ = λ(x : a) -> f (g x)
tetra/base/Data/List.ds view
@@ -1,22 +1,30 @@ module Data.List -export { singleton; replicate- ; enumFromTo- ; append- ; length- ; head- ; tail; tail1- ; last; index- ; reverse - ; map; mapS- ; forS- ; zipWith; zipWithS- ; foldl; foldlS; sum; prod- ; foldr; foldrS- ; scanl- ; filter; filterS- ; any }+export+{ singleton; replicate;+ enumFromTo; append; concat;+ length;+ head;+ tail; tail1;+ last; index;+ lookupBy; find;+ reverse;+ map; mapS; for;+ forS;+ zipWith; zipWithS;+ foldl; foldlS; sum; prod;+ foldr; foldrS;+ scanl;+ filter; filterS;+ any;+} import Data.Numeric.Nat+import Data.Numeric.Bool+import Data.Tuple+import Data.Maybe+import Data.Function+import Class.Functor+import Class.Monad where -- | Standard Cons-lists.@@ -33,13 +41,13 @@ -- | Construct a list of the given length where all elements are' -- the same value.-replicate (n: Nat#) (x: a): List a+replicate (n: Nat) (x: a): List a | n == 0 = Nil | otherwise = Cons x (replicate (n - 1) x) -- | Construct a range of values.-enumFromTo (start: Nat#) (end: Nat#): List Nat#+enumFromTo (start: Nat) (end: Nat): List Nat | start >= end = singleton start | otherwise = Cons start (enumFromTo (start + 1) end) @@ -51,9 +59,35 @@ Cons x xs -> Cons x (append xs yy) +-- | Concatenate a list of lists.+concat (xss0: List (List a)): List a+ = case xss0 of+ Nil -> Nil+ Cons xs xss1 -> go xs xss1+ where+ go Nil Nil = Nil+ go Nil (Cons xs' xss') = go xs' xss'+ go (Cons x xs) xss = Cons x (go xs xss)+++-- | Generate a list of the given length by repeatedly +-- applying a stateful function.+unfold (s0: s) (f: s -> Maybe (Tup2 a s)): List a+ = case f s0 of+ Nothing -> Nil+ Just (T2 a s1) -> Cons a (unfold s1 f)+++generate (len: Nat) (f: Nat -> a): List a+ = unfold 0+ $ (\ix -> if ix >= len + then Nothing+ else Just (T2 (f ix) (ix + 1)))++ -- Projections ---------------------------------------------------------------- -- | Take the length of a list.-length (xx: List a): Nat#+length (xx: List a): Nat = case xx of Nil -> 0 Cons x xs -> 1 + length xs@@ -77,23 +111,19 @@ tail1 (def: a) (xx: List a): List a = case xx of Nil -> singleton def- Cons x xs - -> case xs of- Nil -> singleton x- _ -> xs+ Cons x Nil -> singleton x+ Cons _ xs -> xs -- | Take the last element of a list, if there is one. last (def: a) (xx: List a): a = case xx of Nil -> def- Cons x xs- -> case xs of- Nil -> x- Cons y ys -> last def xs+ Cons x Nil -> x+ Cons x (Cons y ys) -> last def (Cons y ys) -index (def: a) (n: Nat#) (xx: List a): a+index (def: a) (n: Nat) (xx: List a): a = case xx of Nil -> def Cons x xs @@ -102,6 +132,26 @@ _ -> index def (n - 1) xs +-- Searches -------------------------------------------------------------------+-- | Given a list of key value pairs, lookup the first+-- value whose key is selected by the given predicate.+lookupBy (f: a -> Bool) (xx: List (Tup2 a b)): Maybe b+ = case xx of+ Nil -> Nothing+ Cons (T2 x y) xs+ | f x -> Just y+ | otherwise -> lookupBy f xs+++-- | Find the first element in a list that matches the given predicate.+find (f: a -> Bool) (xx: List a): Maybe a+ = case xx of+ Nil -> Nothing+ Cons x xs+ | f x -> Just x+ | otherwise -> find f xs++ -- Transforms ----------------------------------------------------------------- -- | Reverse the elements of a list. -- This is a naive O(n^2) version for testing purposes.@@ -119,6 +169,18 @@ Cons x xs -> Cons (f x) (map f xs) +-- | Like `map`, but with the arguments swapped.+for (xx: List a) (f: a -> b): List b+ = case xx of+ Nil -> Nil+ Cons x xs -> Cons (f x) (for xs f)+++-- | Functor instance for List.+functor_list + = Functor map++ -- | Apply a stateful worker function to every element of a list, -- yielding a new list. -- The worker is applied to the source elements left-to-right.@@ -137,29 +199,37 @@ forS xs f --- Zips ------------------------------------------------------------------------zipWith (f: a -> b -> c) - (xx: List a) (yy: List b): List c+-- | Monadic map.+mapM (dMonad: Monad m) + (f: a -> m b) (xx: List a): m (List b) = case xx of- Nil -> Nil+ Nil + -> return dMonad Nil+ Cons x xs- -> case yy of- Cons y ys- -> Cons (f x y) (zipWith f xs ys)+ -> bind dMonad (f x) $ λx'+ -> bind dMonad (mapM dMonad f xs) $ λxs'+ -> return dMonad (Cons x' xs') - Nil -> Nil +-- Zips -----------------------------------------------------------------------+zipWith (f: a -> b -> c) + (xx: List a) (yy: List b): List c+ = case T2 xx yy of+ T2 Nil _ -> Nil+ T2 (Cons x xs) Nil -> Nil+ T2 (Cons x xs) (Cons y ys)+ -> Cons (f x y) (zipWith f xs ys) ++-- | Stateful zipWith. zipWithS (f: a -> b -> S e c) (xx: List a) (yy: List b): S e (List c)- = case xx of- Nil -> Nil- Cons x xs- -> case yy of- Cons y ys- -> Cons (f x y) (zipWithS f xs ys)-- Nil -> Nil+ = case T2 xx yy of+ T2 Nil _ -> Nil+ T2 (Cons x xs) Nil -> Nil+ T2 (Cons x xs) (Cons y ys)+ -> Cons (f x y) (zipWithS f xs ys) -- Folds ----------------------------------------------------------------------@@ -196,15 +266,20 @@ -- | Take the sum of a list of Nats.-sum (xs: List Nat#): Nat#+sum (xs: List Nat): Nat = foldl (+) 0 xs -- | Take the product of a list of Nats.-prod (xs: List Nat#): Nat#+prod (xs: List Nat): Nat = foldl (*) 1 xs +-- | Monadic sequence.+sequence (dMonad: Monad m) (xs: List (m a)): m (List a)+ = mapM dMonad id xs++ -- Scans ---------------------------------------------------------------------- scanl (f: b -> a -> b) (acc: b) (xx: List a): List b = case xx of@@ -218,31 +293,28 @@ -- Filters -------------------------------------------------------------------- -- | Keep only those elements that match the given predicate.-filter (p: a -> Bool#) (xx: List a): List a+filter (p: a -> Bool) (xx: List a): List a = case xx of Nil -> Nil Cons x xs - -> if p x - then Cons x (filter p xs)- else filter p xs+ | p x -> Cons x (filter p xs)+ | otherwise -> filter p xs -- | Keep only those elements that match the given stateful predicate. -- The predicate is applied to the list elements from left to right.-filterS (p: a -> S e Bool#) (xx: List a): S e (List a)+filterS (p: a -> S e Bool) (xx: List a): S e (List a) = case xx of Nil -> Nil Cons x xs - -> if p x - then Cons x (filterS p xs)- else filterS p xs+ | p x -> Cons x (filterS p xs)+ | otherwise -> filterS p xs -- | Check if any of the members of the list match the given predicate.-any (p: a -> Bool#) (xx: List a): Bool#+any (p: a -> Bool) (xx: List a): Bool = case xx of- Nil- -> False+ Nil -> False Cons x xs | p x -> True
+ tetra/base/Data/Map.ds view
@@ -0,0 +1,325 @@++module Data.Map+export +{ map_empty; map_singleton;+ map_null; map_size;+ map_lookup; map_member;+ map_insert; map_insertWithKey;+ map_foldr; map_foldrWithKey; map_foldlWithKey;+ map_fromList;+ map_toList; map_toAscList; map_toDescList;+ show_map;+}+import Data.Numeric.Nat+import Data.Numeric.Bool+import Data.Text+import Data.Maybe+import Data.List+import Data.Tuple+import Class.Ord+import Class.Show+where+++-- | A map from keys @k@ to values @a@.+data Map (k a: Data) where+ Bin : Size -> k -> a -> Map k a -> Map k a -> Map k a+ Tip : Map k a+++type Size = Nat+++show_map (show_k: Show k) (show_a: Show a): Show (Map k a)+ = Show sh+ where + sh (Bin s k a l r)+ = parens $ "Bin"+ %% show show_nat s+ %% show show_k k+ %% show show_a a+ %% show (show_map show_k show_a) l+ %% show (show_map show_k show_a) r++ sh Tip+ = "Tip"+++-- Construction -----------------------------------------------------------------------------------+-- | O(1). The empty map.+map_empty : Map k a+ = Tip+++-- | O(1). A map with a single element.+map_singleton (k: k) (x: a) : Map k a+ = Bin 1 k x Tip Tip+++-- Query ------------------------------------------------------------------------------------------+-- | /O(1)/. Is the map empty?+--+-- > Data.Map.null (empty) == True+-- > Data.Map.null (singleton 1 'a') == False+map_null (mp: Map k a): Bool+ = case mp of+ Tip -> True+ Bin _ _ _ _ _ -> False+++-- | /O(1)/. The number of elements in the map.+--+-- > size empty == 0+-- > size (singleton 1 'a') == 1+-- > size (fromList([(1,'a'), (2,'c'), (3,'b')])) == 3+map_size (mp: Map k a): Size+ = case mp of+ Tip -> 0+ Bin sz _ _ _ _ -> sz+ ++-- | /O(log n)/. Lookup the value at a key in the map.+--+-- The function will return the corresponding value as @('Just' value)@,+-- or 'Nothing' if the key isn't in the map.+map_lookup ((Ord compare): Ord k) (kx: k) (mp: Map k a): Maybe a+ = go kx mp+ where + go _ Tip + = Nothing [a]++ go k (Bin _ kx x l r)+ = case compare k kx of+ LT -> go k l+ GT -> go k r+ EQ -> Just x+++-- | /O(log n)/. Is the key a member of the map?+--+-- > member 5 (fromList [(5,'a'), (3,'b')]) == True+-- > member 1 (fromList [(5,'a'), (3,'b')]) == False+--+map_member ((Ord compare): Ord k) (kx: k) (mp: Map k a): Bool+ = go kx mp+ where + go _ Tip + = False++ go k (Bin _ kx _ l r)+ = case compare k kx of+ LT -> go k l+ GT -> go k r+ EQ -> True+++-- Insertion --------------------------------------------------------------------------------------+-- | /O(log n)/. Insert a new key and value in the map.+-- If the key is already present in the map, the associated value is+-- replaced with the supplied value. 'insert' is equivalent to+-- @'insertWith' 'const'@.+--+-- > insert 5 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'x')]+-- > insert 7 'x' (fromList [(5,'a'), (3,'b')]) == fromList [(3, 'b'), (5, 'a'), (7, 'x')]+-- > insert 5 'x' empty == singleton 5 'x'+--+map_insert+ ((Ord compare): Ord k) + (kx0: k) (x0: a) (mp: Map k a): Map k a+ = go kx0 x0 mp+ where+ go kx x Tip + = map_singleton kx x++ go kx x (Bin sz ky y l r)+ = case compare kx ky of+ LT -> map_balance ky y (go kx x l) r+ GT -> map_balance ky y l (go kx x r)+ EQ -> Bin sz kx x l r+++-- | /O(log n)/. Insert with a function, combining new value and old value.+-- @'insertWith' f key value mp@+-- will insert the pair (key, value) into @mp@ if key does+-- not exist in the map. If the key does exist, the function will+-- insert the pair @(key, f new_value old_value)@.+--+map_insertWith+ (ord: Ord k)+ (f: a -> a -> a)+ (kx: k) (x: a) (mp: Map k a)+ : Map k a+ = map_insertWithKey ord+ (\_ x' y' -> f x' y')+ kx x mp+++-- | /O(log n)/. Insert with a function, combining key, new value and old value.+-- @'insertWithKey' f key value mp@+-- will insert the pair (key, value) into @mp@ if key does+-- not exist in the map. If the key does exist, the function will+-- insert the pair @(key,f key new_value old_value)@.+-- Note that the key passed to f is the same key passed to 'insertWithKey'.+--+map_insertWithKey+ ((Ord compare): Ord k)+ (f: k -> a -> a -> a)+ (kx: k) (x: a) (mp: Map k a)+ : Map k a+ = go kx x mp+ where+ go kx x Tip+ = map_singleton kx x++ go kx x (Bin sy ky y l r)+ = case compare kx ky of+ LT -> map_balance ky y (go kx x l) r+ GT -> map_balance ky y l (go kx x r)+ EQ -> Bin sy kx (f kx x y) l r+++-- Folds ------------------------------------------------------------------------------------------+-- | /O(n)/. Fold the values in the map using the given right-associative+-- binary operator.+--+map_foldr (f: a -> b -> b) (z: b) (mp: Map k a): b+ = go z mp+ where+ go z' Tip = z'+ go z' (Bin _ _ x l r) = go (f x (go z' r)) l+++-- | /O(n)/. Fold the keys and values in the map using the given right-associative+-- binary operator..+--+map_foldrWithKey (f: k -> a -> b -> b) (z: b) (mp: Map k a): b+ = go z mp+ where+ go z' Tip = z'+ go z' (Bin _ kx x l r) = go (f kx x (go z' r)) l+++-- | /O(n)/. Fold the keys and values in the map using the given left-associative+-- binary operator.+map_foldlWithKey (f: a -> k -> b -> a) (z: a) (mp: Map k b): a+ = go z mp+ where go z' Tip = z'+ go z' (Bin _ kx x l r) = go (f (go z' l) kx x) r+++-- Conversion -------------------------------------------------------------------------------------+map_fromList + (ord: Ord k)+ (xx: List (Tup2 k a))+ : Map k a+ = foldl (λ mp tp+ -> case tp of+ T2 kx x -> map_insert ord kx x mp)+ map_empty xx+++-- | /O(n)/. Convert the map to a list of key\/value pairs. +map_toList (mp: Map k a): List (Tup2 k a)+ = map_toAscList mp+++-- | /O(n)/. Convert the map to a list of key\/value pairs where the+-- keys are in ascending order. +map_toAscList (mp: Map k a): List (Tup2 k a)+ = map_foldrWithKey (λk x xs -> Cons (T2 k x) xs) Nil mp+++-- | /O(n)/. Convert the map to a list of key\/value pairs where the+-- keys are in descending order.+map_toDescList (mp: Map k a): List (Tup2 k a)+ = map_foldlWithKey (λxs k x -> Cons (T2 k x) xs) Nil mp+++---------------------------------------------------------------------------------------------------+-- [balance l x r] balances two trees with value x.+-- The sizes of the trees should balance after decreasing the+-- size of one of them. (a rotation).+--+-- [delta] is the maximal relative difference between the sizes of+-- two trees, it corresponds with the [w] in Adams' paper.+--+-- [ratio] is the ratio between an outer and inner sibling of the+-- heavier subtree in an unbalanced setting. It determines+-- whether a double or single rotation should be performed+-- to restore balance. It is corresponds with the inverse+-- of $\alpha$ in Adam's article.+--+-- Note that according to the Adam's paper:+-- - [delta] should be larger than 4.646 with a [ratio] of 2.+-- - [delta] should be larger than 3.745 with a [ratio] of 1.534.+--+-- But the Adam's paper is erroneous:+-- - It can be proved that for delta=2 and delta>=5 there does+-- not exist any ratio that would work.+-- - Delta=4.5 and ratio=2 does not work.+--+-- That leaves two reasonable variants, delta=3 and delta=4,+-- both with ratio=2.+--+-- - A lower [delta] leads to a more 'perfectly' balanced tree.+-- - A higher [delta] performs less rebalancing.+--+-- In the benchmarks, delta=3 is faster on insert operations,+-- and delta=4 has slightly better deletes. As the insert speedup+-- is larger, we currently use delta=3.+--+-- NOTE: The Haskell implementation from the containers package+-- contains an unfolded version of balance to optimise pattern +-- matching, but there is no point using that until we have the+-- same sort of pattern matching compiler optimisations as GHC.+-- +delta = 2+ratio = 5+++map_balance (k: k) (x: a) (l: Map k a) (r: Map k a): Map k a+ = let sizeL = map_size l in+ let sizeR = map_size r in+ let sizeX = sizeL + sizeR + 1 + in match+ | sizeL + sizeR <= 1 = Bin sizeX k x l r+ | sizeR > delta*sizeL = rotateL k x l r+ | sizeL > delta*sizeR = rotateR k x l r+ | otherwise = Bin sizeX k x l r+++rotateL (k: k) (x: a)+ (l: Map k a) (r@(Bin _ _ _ ly ry): Map k a)+ : Map k a+ | map_size ly < ratio*map_size ry = singleL k x l r+ | otherwise = doubleL k x l r+++rotateR (k: k) (x: a)+ (l@(Bin _ _ _ ly ry): Map k a) (r: Map k a)+ : Map k a+ | map_size ry < ratio*map_size ly = singleR k x l r+ | otherwise = doubleR k x l r+++singleL (k1: k) (x1: a) (t1: Map k a) (tR: Map k a): Map k a+ | Bin _ k2 x2 t2 t3 <- tR+ = bin k2 x2 (bin k1 x1 t1 t2) t3++singleR (k1: k) (x1: a) (tL: Map k a) (t3: Map k a): Map k a+ | Bin _ k2 x2 t1 t2 <- tL+ = bin k2 x2 t1 (bin k1 x1 t2 t3)++doubleL (k1: k) (x1: a) (t1: Map k a) (tR: Map k a): Map k a+ | Bin _ k2 x2 (Bin _ k3 x3 t2 t3) t4 <- tR+ = bin k3 x3 (bin k1 x1 t1 t2) (bin k2 x2 t3 t4)++doubleR (k1: k) (x1: a) (tL: Map k a) (t4: Map k a): Map k a+ | Bin _ k2 x2 t1 (Bin _ k3 x3 t2 t3) <- tL+ = bin k3 x3 (bin k2 x2 t1 t2) (bin k1 x1 t3 t4)+++-- | The bin constructor maintains the size of the tree+bin (k: k) (x: a) (l: Map k a) (r: Map k a): Map k a+ = Bin (map_size l + map_size r + 1) k x l r+
tetra/base/Data/Maybe.ds view
@@ -1,6 +1,10 @@ module Data.Maybe export { isNothing; isJust; fromMaybe }+import Class.Functor+import Class.Applicative+import Class.Monad+import Data.Numeric.Bool where @@ -10,20 +14,73 @@ Just : a -> Maybe a +-- Functor --------------------------------------------------------------------+functor_maybe+ = Functor + maybe_fmap+ where + maybe_fmap : [a b: Data]. (a -> b) -> Maybe a -> Maybe b+ maybe_fmap f xx + = case xx of+ Nothing -> Nothing+ Just x -> Just (f x)+++-- Applicative ----------------------------------------------------------------+applicative_maybe+ = Applicative + functor_maybe + maybe_pure+ maybe_ap+ where+ maybe_pure : [a: Data]. a -> Maybe a+ maybe_pure x+ = Just x++ maybe_ap : [a b: Data]. Maybe (a -> b) -> Maybe a -> Maybe b+ maybe_ap mf ma+ | Just xf <- mf+ , Just xa <- ma+ = Just (xf xa)++ | otherwise+ = Nothing+++-- Monad ----------------------------------------------------------------------+monad_maybe+ = Monad+ applicative_maybe+ maybe_return+ maybe_bind+ where + maybe_return : [a: Data]. a -> Maybe a+ maybe_return x+ = Just x++ maybe_bind : [a b: Data]. Maybe a -> (a -> Maybe b) -> Maybe b+ maybe_bind ma f + = case ma of+ Nothing -> Nothing+ Just xa -> f xa+++-- Predicates ----------------------------------------------------------------- -- | Check if the given value is a `Nothing`.-isNothing (m: Maybe a): Bool#+isNothing (m: Maybe a): Bool = case m of Nothing -> True Just x -> False -- | Check if the given value is a `Just`.-isJust (m: Maybe a): Bool#+isJust (m: Maybe a): Bool = case m of Nothing -> False Just x -> True +-- Destructors ---------------------------------------------------------------- -- | Take the value from a `Just`, or return a default value. fromMaybe (def: a) (m: Maybe a): a = case m of@@ -36,3 +93,4 @@ = case m of Nothing -> def Just x -> f x+
tetra/base/Data/Numeric/Bool.ds view
@@ -1,23 +1,24 @@ module Data.Numeric.Bool-export { not; and; or }+export { not; and; or; } where +type Bool = Bool# -- | Boolean NOT.-not (x: Bool#): Bool#+not (x: Bool): Bool = if x then False else True -- | Boolean AND.-and (x y: Bool#): Bool#+and (x y: Bool): Bool = if x then y else False -- | Boolean OR.-or (x y: Bool#): Bool#+or (x y: Bool): Bool = if x then True else y
tetra/base/Data/Numeric/Nat.ds view
@@ -1,12 +1,18 @@ module Data.Numeric.Nat-export { add; sub; mul; div; rem- ; eq; neq; lt; le; gt; ge- ; shl; shr; band; bor; bxor- ; divMod }+export +{ add; sub; mul; div; rem;+ eq; neq; lt; le; gt; ge;+ shl; shr; band; bor; bxor;+ divMod;+ ord_nat;+} import Data.Tuple+import Class.Ord where +type Nat = Nat#+ ------------------------------------------------------------------------------- -- Names used by the Source Tetra desugarer to implement infix operators. add x y = add# [Nat#] x y@@ -37,7 +43,16 @@ bxor x y = bxor# [Nat#] x y -divMod (n m: Nat#): Tup2 Nat# Nat#+divMod (n m: Nat): Tup2 Nat Nat = T2 (div n m) (rem n m) ++-------------------------------------------------------------------------------+-- Type class instances.+nat_compare n1 n2+ | n1 > n2 = GT+ | n1 < n2 = LT+ | otherwise = EQ++ord_nat = Ord nat_compare
+ tetra/base/Data/Numeric/Word.ds view
@@ -0,0 +1,9 @@++module Data.Numeric.Word+where++type Word8 = Word8#+type Word16 = Word16#+type Word32 = Word32#+type Word64 = Word64#+
tetra/base/Data/Stream.ds view
@@ -1,10 +1,13 @@ module Data.Stream-export { streamOfList; listOfStream- ; sgenerate; senumFrom; srepeat; scons- ; smap; smapacc- ; sfold; sany- ; stake; stakeWhile; sfilter }+export +{ streamOfList; listOfStream;+ sgenerate; senumFrom; srepeat; scons;+ smap; smapacc;+ sfold; sany;+ stake; stakeWhile; + sfilter;+} import Data.Numeric.Nat import Data.List import Data.Maybe@@ -15,6 +18,7 @@ where +------------------------------------------------------------------------------- -- | Unbounded streams, -- wraps a function that produces elements on demand. data Stream (s a: Data) where@@ -26,31 +30,30 @@ Done : Step s a --- Conversions ------------------------------------------------------------------------------------+-- Conversions ---------------------------------------------------------------- -- | Convert a list to a stream. streamOfList (xx: List a): Stream (List a) a- = let step (s1: List a)+ = MkStream step xx+ where + step (s1: List a) = case s1 of Nil -> Done Cons x xs -> Yield x xs- in MkStream step xx -- | Convert a stream to a list.-listOfStream (ss: Stream s a): List a- = case ss of- MkStream f s0- -> case f s0 of- Yield x s1 -> Cons x (listOfStream (MkStream f s1))- Skip s1 -> listOfStream (MkStream f s1)- Done -> Nil+listOfStream (ss: Stream s a): List a+ | MkStream f s0 <- ss+ = case f s0 of+ Yield x s1 -> Cons x (listOfStream (MkStream f s1))+ Skip s1 -> listOfStream (MkStream f s1)+ Done -> Nil -- | Load the given number of elements from a stream and write them -- into a freshly allocated array. arrayOfStream - [r1: Region] - (n: Nat#) -- ^ Length of result array.+ (n: Nat) -- ^ Length of result array. (d: a) -- ^ Default element value. (ss: Stream s a) -- ^ Stream to evaluate. : S (Alloc r1) (Array r1 a)@@ -68,94 +71,101 @@ -- | Unstream all available elements into the given array. unstreamToArray- [r: Region] - (ss: Stream s a) (arr: Array r a) (ix: Nat#)+ (ss: Stream s a) (arr: Array r a) (ix: Nat) : S (Write r) Unit- = case ss of- MkStream f s0- -> case f s0 of+ | MkStream f s0 <- ss+ = go s0 0+ where + go (s: s) (ix: Nat): S (Write r) Unit+ = case f s of Yield x s1 -> do writeArray arr ix x- unstreamToArray (MkStream f s1) arr (ix + 1)+ go s1 (ix + 1) Skip s1- -> unstreamToArray (MkStream f s1) arr ix+ -> go s1 ix Done -> () --- Constructors -----------------------------------------------------------------------------------+-- Constructors --------------------------------------------------------------- -- | Generate a stream, given a starting value and a stepper function. sgenerate (x: s) (step: s -> Tup2 s a): Stream s a- = let step' sA+ = MkStream step' x+ where + step' sA = case step sA of T2 s' x -> Yield x s'- in MkStream step' x -senumFrom (x: Nat#): Stream Nat# Nat#- = sgenerate x (λs: Nat#. T2 (s + 1) s)+senumFrom (x: Nat): Stream Nat Nat+ = sgenerate x (λ(s: Nat) -> T2 (s + 1) s) -- | Create a stream that returns copies of the same value. srepeat (x: a): Stream a a- = sgenerate x (λs: a. T2 s s)+ = sgenerate x (λ(s: a) -> T2 s s) -- | Cons an element to the front of a stream.-scons (x: a) (ss: Stream s a): Stream (Tup2 s Bool#) a- = case ss of- MkStream stepA sA0- -> let stepA2 q- = case q of- T2 sA1 b- -> case b of- True -> Yield x (T2 sA1 False)- False -> case stepA sA1 of- Yield y sA2 -> Yield y (T2 sA2 False)- Skip sA2 -> Skip (T2 sA2 False)- Done -> Done- in MkStream stepA2 (T2 sA0 True)+scons (x: a) (ss: Stream s a)+ : Stream (Tup2 s Bool) a+ | MkStream stepA sA0 <- ss+ = MkStream stepA2 (T2 sA0 True)+ where + stepA2 (T2 sA1 True)+ = Yield x (T2 sA1 False) + stepA2 (T2 sA1 False)+ = case stepA sA1 of+ Yield y sA2 -> Yield y (T2 sA2 False)+ Skip sA2 -> Skip (T2 sA2 False)+ Done -> Done --- Maps -------------------------------------------------------------------------------------------++-- Maps ----------------------------------------------------------------------- -- | Apply a function to every element of a stream.-smap (f: a -> b) (ss: Stream s a): Stream s b- = case ss of - MkStream stepA sA0- -> let stepB q - = case stepA q of- Yield x sA1 -> Yield (f x) sA1- Skip sA2 -> Skip sA2- Done -> Done- in MkStream stepB sA0+smap (f: a -> b) + (ss: Stream s a)+ : Stream s b+ | MkStream stepA sA0 <- ss+ = MkStream stepB sA0+ where+ stepB q + = case stepA q of+ Yield x sA1 -> Yield (f x) sA1+ Skip sA2 -> Skip sA2+ Done -> Done --- Scans ------------------------------------------------------------------------------------------+-- Scans ---------------------------------------------------------------------- -- | Like `smap`, but keep a running accumulator as we walk along the stream.-smapacc (f: a -> b -> Tup2 a c) (z: a) - (ss: Stream s b): Stream (Tup2 s a) c- = case ss of- MkStream fB sB0- -> let stepC q- = case q of- T2 sB1 xA1- -> case fB sB1 of- Yield xB1 sB2 - -> case f xA1 xB1 of- T2 xA2 xC2- -> Yield xC2 (T2 sB2 xA2)- Skip sB2 -> Skip (T2 sB2 xA1)- Done -> Done- in MkStream stepC (T2 sB0 z)+smapacc : [a b c s: Data]+ . (a -> b -> Tup2 a c)+ -> a+ -> Stream s b+ -> Stream (Tup2 s a) c +smapacc f z (MkStream fB sB0)+ = MkStream stepC (T2 sB0 z)+ where+ stepC (T2 sB1 xA1)+ = case fB sB1 of+ Yield xB1 sB2 + -> case f xA1 xB1 of+ T2 xA2 xC2+ -> Yield xC2 (T2 sB2 xA2)+ Skip sB2 -> Skip (T2 sB2 xA1)+ Done -> Done --- Folds ------------------------------------------------------------------------------------------++-- Folds ---------------------------------------------------------------------- -- | Fold all the elements from a stream.-sfold (f: a -> b -> a) (acc: a) (ss: Stream s b): a- = case ss of- MkStream step s0 - -> sconsume f acc step s0+sfold (f: a -> b -> a) + (acc: a) + ((MkStream step s0): Stream s b)+ : a+ = sconsume f acc step s0 sconsume (f: a -> b -> a) (acc: a) @@ -168,54 +178,57 @@ -- | Check if any of the elements of this stream are true, -- demanding only the prefix of non-true elements from the stream.-sany [s: Data] (ss: Stream s Bool#): Bool#+sany [s: Data] (ss: Stream s Bool): Bool = sfold or False $ stakeWhile id ss --- Projections ------------------------------------------------------------------------------------+-- Projections ---------------------------------------------------------------- -- | Take the given number of elements from a stream.-stake (n: Nat#) (ss: Stream s a): Stream (Tup2 s Nat#) a- = case ss of- MkStream fA sA0- -> let stepB q- = case q of- T2 sA ix - | ix >= n -> Done- | otherwise - -> case fA sA of- Yield x sA2 -> Yield x (T2 sA2 (ix + 1))- Skip sA3 -> Skip (T2 sA3 ix)- Done -> Done- in MkStream stepB (T2 sA0 0)+stake (n: Nat)+ ((MkStream fA sA0): Stream s a)+ : Stream (Tup2 s Nat) a + = MkStream stepB (T2 sA0 0)+ where + stepB (T2 sA ix)+ | ix >= n = Done+ | otherwise + = case fA sA of+ Yield x sA2 -> Yield x (T2 sA2 (ix + 1))+ Skip sA3 -> Skip (T2 sA3 ix)+ Done -> Done --- | Take elements from a strem while they match the given predicate.-stakeWhile (p: a -> Bool#) (ss: Stream s a): Stream s a- = case ss of- MkStream stepA sA0- -> let stepB q- = case stepA q of- Yield x sA1 - | p x -> Yield x sA1- | otherwise -> Done [s] [a] - Skip sA1 -> Skip sA1- Done -> Done+-- | Take elements from a stream while they match the given predicate.+stakeWhile + (p: a -> Bool) + ((MkStream stepA sA0): Stream s a)+ : Stream s a - in MkStream stepB sA0+ = MkStream stepB sA0+ where + stepB (q: s)+ = case stepA q of+ Yield x sA1 + | p x -> Yield x sA1+ | otherwise -> Done + Skip sA1 -> Skip sA1+ Done -> Done + -- | Take elements from a stream that match the given predicate.-sfilter (p: a -> Bool#) (ss: Stream s a): Stream s a- = case ss of- MkStream stepA sA0- -> let stepB q- = case stepA q of- Yield x sA1 - | p x -> Yield x sA1- | otherwise -> Skip sA1+sfilter (p: a -> Bool)+ ((MkStream stepA sA0): Stream s a)+ : Stream s a+ = MkStream stepB sA0+ where+ stepB (q: s)+ = case stepA q of+ Yield x sA1 + | p x -> Yield x sA1+ | otherwise -> Skip sA1 - Skip sA1 -> Skip sA1- Done -> Done+ Skip sA1 -> Skip sA1+ Done -> Done - in MkStream stepB sA0
tetra/base/Data/Text.ds view
@@ -1,308 +1,6 @@ module Data.Text -export -{ -- * Construction- textLit; textOfVector; vectorOfText;- paste; pastes;-- -- * Projections- sizeOfText;-- -- * Conversions- copyTextToVector;- copyTextLitToVector;- copyTextVecToVector;-- -- * Operators- textOfWord8;-- -- * Showing- showBool;- showNat; showBinaryNat; showDecimalNat; showHexNat; showBaseNat;- digitBinary; digitDecimal; digitHex;-}-import Data.Numeric.Nat-import Data.Numeric.Bool-import Data.Function-import Data.List----- | The TextLit type is define in the runtime system and contains--- a pointer to the literal utf-8 text data in static memory.-import foreign boxed type- TextLit : Data----- | Runtime functions for dealing with unboxed text literals.-import foreign c value-- -- | Box a text literal.- makeTextLit : TextLit# -> TextLit-- -- | Get the size of a boxed text literal.- sizeOfTextLit : TextLit -> Nat#-- -- | Get a single byte from a boxed text literal.- indexTextLit : TextLit -> Nat# -> Word8#----- | Top level region containing text vectors.-import foreign abstract type- RegionText : Region----- | Capabilities to allocate and read top-level text vectors.-import foreign abstract capability- capTopTextAlloc : Alloc RegionText- capTopTextRead : Read RegionText--where------------------------------------------------------------------------------------- Names used by the Source Tetra desugarer to implement string literals.-textLit (x : TextLit#) : Text- = TextLit (makeTextLit x)--paste (x y : Text) : Text- = TextApp x y--pastes (x y : Text) : Text- = x % " " % y-----------------------------------------------------------------------------------data Text where- TextLit : TextLit -> Text- TextVec : Vector# RegionText Word8# -> Text- TextApp : Text -> Text -> Text----- Construction ------------------------------------------------------------------ | O(1). Wrap a vector of utf8 data into a text object.-textOfVector (vec: Vector# RegionText Word8#): Text- = TextVec vec----- | Copy a Text object into a flat vector of utf-8 bytes.-vectorOfText [r1: Region] (tt: Text)- : S (Alloc r1) (Vector# r1 Word8#)- = extend r1 using r2 with { Alloc r2; Write r2 } in- do - -- Allocate a vector to hold all the data, - -- including an extra null terminator byte.- vec = vectorAlloc# [r2] [Word8#] (add (sizeOfText tt) 1)-- -- Copy the text data into the vector.- iEnd = copyTextToVector tt vec 0-- -- Write the null terminator.- vectorWrite# vec iEnd 0w8-- vec----- | Wrap a single 8-bit character into a text object.----textOfWord8 (w8: Word8#): Text- = TextVec- (extend RegionText using r1 with { Alloc r1; Write r1 } in- do -- Allocate the vector to hold the data,- -- including an extra null terminator byte.- vec = vectorAlloc# [r1] [Word8#] 2-- -- Write the character.- vectorWrite# vec 0 w8-- -- Write the null terminator.- vectorWrite# vec 1 0w8-- vec)----- Projections ------------------------------------------------------------------- | Get the size of the utf8 data in a Text object, in bytes.------ * This is NOT the same as the length of the text string in characters,--- as single characters can be encoded using multiple bytes.----sizeOfText (tt: Text): Nat#- = case tt of- TextLit lit- -> sizeOfTextLit lit-- -- The size of a text vector is the vector size minus- -- the null terminator byte.- TextVec vec - -> vectorLength# vec - 1-- TextApp t1 t2- -> sizeOfText t1 + sizeOfText t2----- Conversions ------------------------------------------------------------------- | Copy a text literal to a mutable vector of utf-8 bytes.-copyTextToVector - [r: Region] (tt: Text) (vec: Vector# r Word8#) (i0: Nat#)- : S (Write r) Nat#- = case tt of- TextLit lit- -> copyTextLitToVector lit vec i0 0 (sizeOfTextLit lit)-- TextVec vec2- -> copyTextVecToVector vec2 vec i0 0 (vectorLength# vec2)-- TextApp t1 t2- -> do i1 = copyTextToVector t1 vec i0- i2 = copyTextToVector t2 vec i1- i2----- | Copy a text literal to a mutable vector of utf-8 bytes.-copyTextLitToVector - [r: Region] (tt: TextLit) (vec: Vector# r Word8#) - (iDst iSrc nSrc: Nat#)- : S (Write r) Nat#- = case iSrc >= nSrc of- True -> iDst- False - -> do vectorWrite# vec iDst (indexTextLit tt iSrc)-- copyTextLitToVector - tt vec (iDst + 1) (iSrc + 1) nSrc----- | Copy a text source vector to a mutable destination of utf-8 bytes.-copyTextVecToVector - [r1 r2: Region] - (vecSrc: Vector# r1 Word8#) (vecDst: Vector# r2 Word8#)- (iDst iSrc nSrc: Nat#)- : S (Read r1 + Write r2) Nat#- = case iSrc >= nSrc of- True -> iDst-- False -> do- vectorWrite# vecDst iDst (vectorRead# vecSrc iSrc)-- copyTextVecToVector - vecSrc vecDst (iDst + 1) (iSrc + 1) nSrc----- Operators --------------------------------------------------------------------- | If this text is not already in flat form then flatten it.------ This allocates a new contiguous vector for the text object and--- allows the program to release space for intermediate append nodes.----flattenText (tt: Text): Text- = case tt of- -- Single text literals are already flat.- TextLit lit -> tt-- -- Single text vectors are already flat.- TextVec vec -> tt-- -- Text has an outer append-node, - -- so flatten the whole thing.- TextApp _ _ -> textOfVector (run vectorOfText [RegionText] tt)----- Showing ----------------------------------------------------------------------- | Convert a Bool to a String.-showBool (x : Bool#) : Text- = if x then "True" - else "False"----- | Show a natural number.-showNat (x: Nat#): Text- = showBaseNat 10 digitDecimal 0 "X" x------------------------------------------------------------------------------------- | Show a natural number, in binary.-showBinaryNat (x: Nat#): Text- = showBaseNat 2 digitBinary 0 "X" x--digitBinary (n: Nat#): Text- = case n of- 0 -> "0"- 1 -> "1"- _ -> "X"----- | Show a natural number in decimal.-showDecimalNat (x: Nat#): Text- = showBaseNat 10 digitDecimal 0 "X" x--digitDecimal (n: Nat#): Text- = case n of- 0 -> "0"- 1 -> "1"- 2 -> "2"- 3 -> "3"- 4 -> "4"- 5 -> "5"- 6 -> "6"- 7 -> "7"- 8 -> "8"- 9 -> "9"- _ -> "X"----- | Show a natural number in hex.-showHexNat (x: Nat#): Text- = showBaseNat 16 digitHex 0 "X" x--digitHex (n: Nat#): Text- = case n of- 0 -> "0"- 1 -> "1"- 2 -> "2"- 3 -> "3"- 4 -> "4"- 5 -> "5"- 6 -> "6"- 7 -> "7"- 8 -> "8"- 9 -> "9"- 10 -> "a"- 11 -> "b"- 12 -> "c"- 13 -> "d"- 14 -> "e"- 15 -> "f"- _ -> "X"------------------------------------------------------------------------------------- | Show a natural number using an arbitrary base encoding.-showBaseNat - (base: Nat#) -- ^ Base of encoding.- (digit: Nat# -> Text) -- ^ Show a digit in this base.- (width: Nat#) -- ^ Width of output, or 0 to not pad.- (pad: Text) -- ^ Character to pad output with.- (x: Nat#) -- ^ Number to print.- : Text-- = do s = showBaseNat' base digit width pad True x- if x < 0 - then "-" % s - else s--showBaseNat' base digit width pad first x- | and (x == 0) first- = showBaseNat' base digit (width - 1) pad False x- % "0"-- | and (x == 0) (width > 0)- = showBaseNat' base digit (width - 1) pad False x- % pad-- | x == 0- = ""-- | otherwise- = showBaseNat' base digit (width - 1) pad False (div x base) - % digit (rem x base) -+import Data.Text.Base+import Data.Text.List+import Data.Text.Operator+import Data.Text.Show
+ tetra/base/Data/Text/Base.ds view
@@ -0,0 +1,244 @@++-- | Basic types and operators on Text objects.+module Data.Text.Base+export+{ -- Runtime operators.+ makeTextLit;+ sizeOfTextLit;+ indexTextLit;++ -- Construction.+ textOfChar;+ textOfWord8;+ textOfVector;++ -- Conversion.+ vectorOfText;++ -- Projections.+ sizeOfText;+ indexText;++ -- Operators.+ eqText;+}+import Data.Text.Char+import Data.Numeric.Nat+import Data.Numeric.Word+import Data.Maybe+++-------------------------------------------------------------------------------+-- Foreign imports.++-- | A TextLit is a boxed object that contains a pointer to literal+-- UTF-8 data in static memory. +import foreign boxed type+ TextLit : Data+++-- | Runtime operators for working with unboxed text literals.+import foreign c value++ -- | Make a text literal.+ -- The TextLit# type is a pointer to literal UTF-8 data in + -- static memory, which we pack into a boxed object.+ makeTextLit : TextLit# -> TextLit++ -- | Get the size of a boxed text literal.+ sizeOfTextLit : TextLit -> Nat#++ -- | Get a single byte from a boxed text literal.+ -- This is a byte rather than a character,+ -- as UTF-8 encoded characters can consist of multiple bytes.+ indexTextLit : TextLit -> Nat# -> Word8#+++-- | Top level region containing text vectors.+-- All our dynamic character data is in this region.+import foreign abstract type+ RegionText : Region+++-- | Capabilities to allocate and read top-level text vectors.+import foreign abstract capability+ capTopTextAlloc : Alloc RegionText+ capTopTextRead : Read RegionText++where+++-- Text -----------------------------------------------------------------------+data Text where+ -- | Wrap a text literal into a text object.+ -- The characterdata is stored in static memory.+ TextLit : TextLit -> Text++ -- | Wrap some character data into a text object.+ -- The character data is stored on the heap.+ TextVec : Vector# RegionText Word8# -> Text++ -- | Append two text objects.+ TextApp : Text -> Text -> Text+++-- Construction ---------------------------------------------------------------+-- | O(1). Wrap a single character into a text object.+-- We're only taking the lowest 8 bit bytes,+-- rather than doing proper UTF-8 encoding.+textOfChar (c: Word32): Text+ = textOfWord8 (truncate# c)+++-- | O(1). Wrap a single byte into a text object.+textOfWord8 (w8: Word8): Text+ = TextVec+ $ extend RegionText using r1 with { Alloc r1; Write r1 } in+ do -- Allocate the vector to hold the data,+ -- including an extra null terminator byte.+ vec = vectorAlloc# [r1] 2++ -- Write the character.+ vectorWrite# vec 0 w8++ -- Write the null terminator.+ vectorWrite# vec 1 0w8++ vec+++-- | O(1). Wrap a vector of UTF-8 data into a text object.+textOfVector (vec: Vector# RegionText Word8): Text+ = TextVec vec+++-- Conversion -----------------------------------------------------------------+-- | Copy a Text object into a flat vector of UTF-8 data.+vectorOfText+ [r1: Region] (tt: Text)+ : S (Alloc r1) (Vector# r1 Word8)+ = extend r1 using r2 with { Alloc r2; Write r2 } in+ do + -- Allocate a vector to hold all the data, + -- including an extra null terminator byte.+ vec = vectorAlloc# [r2] (add (sizeOfText tt) 1)++ -- Copy the text data into the vector.+ iEnd = copyTextToVector tt vec 0++ -- Write the null terminator.+ vectorWrite# vec iEnd 0w8++ vec+++-- | Copy a text object to a mutable vector of UTF-8 data.+copyTextToVector + [r: Region] (tt: Text) (vec: Vector# r Word8) (i0: Nat)+ : S (Write r) Nat+ = case tt of+ TextLit lit+ -> copyTextLitToVector lit vec i0 0 (sizeOfTextLit lit)++ TextVec vec2+ -> copyTextVecToVector vec2 vec i0 0 (vectorLength# vec2 - 1)++ TextApp t1 t2+ -> do i1 = copyTextToVector t1 vec i0+ i2 = copyTextToVector t2 vec i1+ i2+++-- | Copy a text literal to a mutable vector of UTF-8 data.+copyTextLitToVector + [r: Region] (tt: TextLit) (vec: Vector# r Word8) + (iDst iSrc nSrc: Nat)+ : S (Write r) Nat+ | iSrc >= nSrc = iDst+ | otherwise+ = do vectorWrite# vec iDst (indexTextLit tt iSrc)+ copyTextLitToVector + tt vec (iDst + 1) (iSrc + 1) nSrc+++-- | Copy a text source vector to a mutable vector of UTF-8 data.+copyTextVecToVector + [r1 r2: Region] + (vecSrc: Vector# r1 Word8) (vecDst: Vector# r2 Word8)+ (iDst iSrc nSrc: Nat)+ : S (Read r1 + Write r2) Nat+ | iSrc >= nSrc = iDst+ | otherwise+ = do vectorWrite# vecDst iDst (vectorRead# vecSrc iSrc)+ copyTextVecToVector + vecSrc vecDst (iDst + 1) (iSrc + 1) nSrc+++-- Projections ----------------------------------------------------------------+-- | Get the size of the utf8 data in a Text object, in bytes.+--+-- * This is NOT the same as the length of the text string in characters,+-- as single characters can be encoded using multiple bytes.+--+sizeOfText (tt: Text): Nat+ = case tt of+ TextLit lit+ -> sizeOfTextLit lit++ -- The size of a text vector is the vector size minus+ -- the null terminator byte.+ TextVec vec + -> vectorLength# vec - 1++ TextApp t1 t2+ -> sizeOfText t1 + sizeOfText t2+++-- | Get a single word8 character from a Text object.+indexText (tt: Text) (ix: Nat): Maybe Word8+ = case tt of+ TextLit lit+ | ix >= sizeOfTextLit lit -> Nothing+ | otherwise -> Just (indexTextLit lit ix)++ TextVec vec+ | ix >= vectorLength# vec - 1 -> Nothing+ | otherwise -> Just (vectorRead# vec ix)++ TextApp t1 t2+ -> case indexText t1 ix of+ Just x -> Just x+ Nothing -> indexText t2 (ix - sizeOfText t1)+++-- Comparison -----------------------------------------------------------------+-- | O(max len1 len2).+-- Check if two text objects represent the same characters.+eqText (tx1 tx2: Text): Bool+ = private r with {Read r; Alloc r} in+ do + -- We copy both strings into new vectors before doing the comparison.+ -- It would be better to do it in-place.+ vec1 = vectorOfText [r] tx1 + len1 = vectorLength# vec1++ vec2 = vectorOfText [r] tx2+ len2 = vectorLength# vec2++ match+ | len1 /= len2 = False+ | len1 == 0 = True+ | otherwise = go vec1 vec2 len1 0++ where+ go (vec1 vec2: Vector# r Word8)+ (len: Nat) (ix: Nat): S (Read r) Bool+ | ix >= (len - 1)+ = True++ | not (eq# (vectorRead# vec1 ix) (vectorRead# vec2 ix))+ = False++ | otherwise+ = go vec1 vec2 len (ix + 1)+
+ tetra/base/Data/Text/Char.ds view
@@ -0,0 +1,28 @@++module Data.Text.Char+export+{ isDigit;+ isUpper;+ isLower;+}+import Data.Numeric.Bool+where++-- Character literals are special syntax for a unicode codepoint+-- represented as a 32-bit word.+type Char = Word32#+++-- | Check if a character is a digit.+isDigit (c: Char): Bool+ = ge# c 0x030w32 ∧ le# c 0x039w32+++-- | Check if a character is an upper-case letter.+isUpper (c: Char): Bool+ = ge# c 65w32 ∧ le# c 90w32+++-- | Check if a character is a lower-case letter.+isLower (c: Char): Bool+ = ge# c 97w32 ∧ le# c 122w32
+ tetra/base/Data/Text/List.ds view
@@ -0,0 +1,66 @@++-- | Conversions between Text and Lists.+module Data.Text.List+export +{ textOfCharList;+ charListOfText;+}+import Data.Numeric.Word+import Data.Text.Base+import Data.Text.Char+import Data.List+where+++-- | Convert a list of characters to a Text object.+textOfCharList (xx: List Char): Text+ = TextVec+ $ extend RegionText using r with { Alloc r; Read r; Write r }+ in vectorOfCharList [r] xx+++-- | O(n). Convert a text object to a list of characters.+charListOfText (tx: Text): List Char+ = case tx of+ TextVec vec -> charListOfTextVec vec+ _ -> charListOfTextVec (vectorOfText [RegionText] tx)+++-- | Unpack a list of characters from a vector.+charListOfTextVec+ (vec: Vector# r Word8)+ : S (Read r) (List Char)+ = go 0+ where + go (ix: Nat): S (Read r) (List Char)+ | ix >= (vectorLength# vec - 1)+ = Nil++ | otherwise + = do txChar = promote# (vectorRead# vec ix)+ Cons txChar (go (ix + 1))+++-- | Pack a list of characters into a mutable vector.+vectorOfCharList+ [r: Region]+ (xx: List Char)+ : S (Alloc r + Write r) (Vector# r Word8)+ = do+ len = length xx+ vec = vectorAlloc# [r] (len + 1)++ fill (ix: Nat) (xx: List Char): S (Write r) Unit+ = case xx of+ Nil -> ()+ Cons x xs+ -> do vectorWrite# vec ix (truncate# x)+ fill (ix + 1) xs++ | otherwise+ -> do fill (ix + 1) xs+ fill 0 xx++ vectorWrite# vec len 0w8+ vec+
+ tetra/base/Data/Text/Operator.ds view
@@ -0,0 +1,54 @@++-- | Useful operators on text objects.+module Data.Text.Operator+export+{ -- * Desugaring+ textLit; paste; pastes;++ -- * Optimizations+ flattenText;++ -- * Pretty Printing+ parens;+}+import Data.Text.Base+where+++-- Desuguaring -----------------------------------------------------------------+-- Names used by the Source Tetra desugarer to implement string literals.+textLit (x : TextLit#) : Text+ = TextLit (makeTextLit x)++paste (x y : Text) : Text+ = TextApp x y++pastes (x y : Text) : Text+ = x % " " % y+++-- Optimizations --------------------------------------------------------------+-- | If this text is not already in flat form then flatten it.+--+-- This allocates a new contiguous vector for the text object and+-- allows the program to release space for intermediate append nodes.+--+flattenText (tt: Text): Text+ = case tt of+ -- Single text literals are already flat.+ TextLit lit -> tt++ -- Single text vectors are already flat.+ TextVec vec -> tt++ -- Text has an outer append-node, + -- so flatten the whole thing.+ TextApp _ _ -> textOfVector (run vectorOfText [RegionText] tt)+++-- Pretty Printing ------------------------------------------------------------+-- | Wrap a some text in parenthesis.+parens (tx: Text): Text+ = "(" % tx % ")"++
+ tetra/base/Data/Text/Show.ds view
@@ -0,0 +1,119 @@++-- | Showing various data types as text.+module Data.Text.Show+export+{ showBool;++ showNat;+ showBinaryNat; digitBinary;+ showDecimalNat; digitDecimal;+ showHexNat; digitHex;+ showBaseNat;+}+import Data.Numeric.Word+import Data.Text.Base+import Data.Text.Char+import Data.Text.Operator+where+++-------------------------------------------------------------------------------+-- | Convert a Bool to a String.+showBool (x : Bool): Text+ = if x then "True" + else "False"+++-- | Show a natural number.+showNat (x: Nat): Text+ = showBaseNat 10 digitDecimal 0 'X' x+++-------------------------------------------------------------------------------+-- | Show a natural number, in binary.+showBinaryNat (x: Nat): Text+ = showBaseNat 2 digitBinary 0 'X' x++digitBinary (n: Nat): Char+ = case n of+ 0 -> '0'+ 1 -> '1'+ _ -> 'X'+++-------------------------------------------------------------------------------+-- | Show a natural number in decimal.+showDecimalNat (x: Nat): Text+ = showBaseNat 10 digitDecimal 0 'X' x++digitDecimal (n: Nat): Word32+ = case n of+ 0 -> '0'+ 1 -> '1'+ 2 -> '2'+ 3 -> '3'+ 4 -> '4'+ 5 -> '5'+ 6 -> '6'+ 7 -> '7'+ 8 -> '8'+ 9 -> '9'+ _ -> 'X'+++-------------------------------------------------------------------------------+-- | Show a natural number in hex.+showHexNat (x: Nat): Text+ = showBaseNat 16 digitHex 0 'X' x++digitHex (n: Nat): Char+ = case n of+ 0 -> '0'+ 1 -> '1'+ 2 -> '2'+ 3 -> '3'+ 4 -> '4'+ 5 -> '5'+ 6 -> '6'+ 7 -> '7'+ 8 -> '8'+ 9 -> '9'+ 10 -> 'a'+ 11 -> 'b'+ 12 -> 'c'+ 13 -> 'd'+ 14 -> 'e'+ 15 -> 'f'+ _ -> 'X'+++-------------------------------------------------------------------------------+-- | Show a natural number using an arbitrary base encoding.+showBaseNat + (base: Nat) -- ^ Base of encoding.+ (digit: Nat -> Char) -- ^ Show a digit in this base.+ (width: Nat) -- ^ Width of output, or 0 to not pad.+ (pad: Char) -- ^ Character to pad output with.+ (x: Nat) -- ^ Number to print.+ : Text+ = do s = showBaseNat' base digit width pad True x+ if x < 0 + then "-" % s + else s++showBaseNat' base digit width pad first x+ | and (x == 0) first+ = showBaseNat' base digit (width - 1) pad False x + % "0"++ | and (x == 0) (width > 0)+ = showBaseNat' base digit (width - 1) pad False x+ % textOfChar pad++ | x == 0 + = ""++ | otherwise+ = showBaseNat' base digit (width - 1) pad False (div x base) + % textOfChar (digit (rem x base))+
tetra/base/Math/Combinations.ds view
@@ -6,37 +6,36 @@ import Data.List where + -- | Compute the factorial of a number. -- -- factorial n is the number of possible permutations -- of a sequence of n things. ---factorial (n: Nat#): Nat#- = if n == 0- then 1- else n * factorial (n - 1)+factorial (n: Nat): Nat+ | n == 0 = 1+ | otherwise = n * factorial (n - 1) --- | Compute the number of was of choosing r things from n things.+-- | Compute the number of ways of choosing r things from n things. --- -- Note that the textbook definition of this is, -- div (factorial n) ( factorial (n - 1) * factorial r ) -- but we factor out the (factorial (n - 1)) term beforehand to -- make it easier to compute. ---choose (n r: Nat#): Nat#- = if r > n - then 0- else div (prodRange n (n - (r - 1))) (factorial r)+choose (n r: Nat): Nat+ | r > n = 0+ | otherwise = div (prodRange n (n - (r - 1))) (factorial r) + -- | Compute the product of the range [n, n-1 .. m] inclusive.-prodRange (n m: Nat#): Nat#- = if n == m- then n- else n * prodRange (n - 1) m+prodRange (n m: Nat): Nat+ | n == m = n+ | otherwise = n * prodRange (n - 1) m -- | Compute the number of ways of choosing collections of things -- of sizes rs from n things.-chooseMany (n: Nat#) (rs: List Nat#): Nat#+chooseMany (n: Nat) (rs: List Nat): Nat = div (factorial n) (prod (map factorial rs))