on master help sign in
Various additions to contrib (#4343)

* Wrote Data.{SortedBag,ArrowChain,PosNat} * Added some more docs to Data.SortedBag * Renamed ArrowChain to Chain * Added `null` to Data.SortedMap * Edited CHANGELOG * Edited contrib.ipkg * Fixed tiny typo

commit2be6e6a7d91098831b29cd5bca48c3a1303a78c5 authorPatrick Hilhorst <patrickhilhorst97@gmail.com> dateFri 23 Feb 2018, 09:36 (9 years ago) parentecd3bc6
8 files changed+238−4
CHANGELOG.md+7−2 libs/contrib/Data/BoundedList.idr+14 libs/contrib/Data/Chain.idr+46 libs/contrib/Data/Combinators.idr+1−2 libs/contrib/Data/PosNat.idr+39 libs/contrib/Data/SortedBag.idr+123 libs/contrib/Data/SortedMap.idr+5 libs/contrib/contrib.ipkg+3
CHANGELOG.md+7−2
@@ -2,6 +2,11 @@
22
33+ REPL now prints an error message if program compiled by `:exec` terminates
44 abnormally.
5++ Additions to `contrib`:
6+ * `Data.SortedBag`: Bag (or Multiset) implemention based on `Data.SortedMap`.
7+ * `Data.PosNat`: A `Nat` paired with a proof that it is positive.
8+ * `Data.Chain`: A function with an arbitrary number of arguments, plus
9+ combinators for working with them.
510
611## Library Updates
712
@@ -42,7 +47,7 @@
4247+ C FFI now supports pasting in any expression by prefixing it with '#', e.g.
4348 ```idris
4449 intMax : IO Int
45− intMax = foreign FFI_C "#INT_MAX" (IO Int)
50+ intMax = foreign FFI_C "#INT_MAX" (IO Int)
4651 ```
4752+ The deprecated keywords `%assert_total`, `abstract`, and `[static]` have
4853 been removed as well as the use of "public" instead of "public export" to
@@ -93,7 +98,7 @@
9398+ Removed several deprecated items from the libraries shipped with Idris.
9499+ Moved `abs` from the `Neg` interface into its own `Abs` interface. `Nat`
95100 implements `Abs` with `abs = id`.
96−+ Added `Control.ST.File`, an ST based implementation of the same behaviour
101++ Added `Control.ST.File`, an ST based implementation of the same behaviour
97102 implemented by `Effect.File` in the effects package.
98103
99104## Tool Updates
libs/contrib/Data/BoundedList.idr+14
@@ -76,6 +76,20 @@ implementation Functor (BoundedList n) where
7676 map f [] = []
7777 map f (x :: xs) = f x :: map f xs
7878
79+--------------------------------------------------------------------------------
80+-- Monoid
81+--------------------------------------------------------------------------------
82+
83+implementation Semigroup a => Semigroup (BoundedList n a) where
84+ (x :: xs) <+> (y :: ys) = (x <+> y) :: (xs <+> ys)
85+ xs <+> [] = xs
86+ [] <+> ys = ys
87+
88+-- The Semigroup constraint is only needed because that's how we make a
89+-- semigroup from BoundedList, not used in this implementation.
90+implementation Semigroup a => Monoid (BoundedList n a) where
91+ neutral = []
92+
7993--------------------------------------------------------------------------------
8094-- Misc
8195--------------------------------------------------------------------------------
libs/contrib/Data/Chain.idrnew file+46
@@ -0,0 +1,46 @@
1+module Data.Chain
2+
3+import Data.Vect
4+import Control.Isomorphism
5+
6+%default total
7+%access public export
8+
9+||| Repeated function application
10+Chain : Nat -> (i, o : Type) -> Type
11+Chain Z _ o = o
12+Chain (S k) i o = i -> Chain k i o
13+
14+||| Repeated endofunction application
15+EndoChain : Nat -> Type -> Type
16+EndoChain n t = Chain n t t
17+
18+||| (.) generalized to any number of arguments.
19+after : (o -> o') -> (Chain n i o) -> (Chain n i o')
20+after {n=Z} f x = f x
21+after {n=S k} f fs = after f . fs
22+
23+||| `on` generalized to any number of arguments
24+before : (i -> i') -> (Chain n i' o) -> (Chain n i o)
25+before {n=Z} _ x = x
26+before {n=S k} f fs = (f `before`) . (fs . f)
27+
28+||| Fill in the same argument for all items (available for a single argument as
29+||| Data.Combinators.reflex)
30+reflexes : (Chain n i o) -> (i -> o)
31+reflexes {n=Z} x _ = x
32+reflexes {n=S k} fs y = reflexes (fs y) y
33+
34+||| Create a vect of a given length from the arguments given.
35+packVect : Chain n i (Vect n i)
36+packVect {n=Z} = []
37+packVect {n=S k} = (`after` packVect) . Data.Vect.(::)
38+-- For some reason we get a can't disambiguate name: Prelude.List.::,
39+-- Prelude.Stream.::, Data.Vect.:: if we leave out the Data.Vect specification
40+
41+||| Apply a function over a vector to our new type
42+fromVectFunc : (Vect n i -> o) -> (Chain n i o)
43+fromVectFunc f = (f `after` packVect)
44+
45+withIso : Iso t t' -> EndoChain n t -> EndoChain n t'
46+withIso (MkIso to from _ _) = (from `before`) . (to `after`)
libs/contrib/Data/Combinators.idr+1−2
@@ -5,8 +5,7 @@
55||| hasn't actually read). See
66||| http://www.angelfire.com/tx4/cus/combinator/birds.html and
77||| https://hackage.haskell.org/package/data-aviary-0.4.0/docs/Data-Aviary-Birds.html
8−||| an (incomplete?) list of birds introduced. Also includes some operations defined
9−||| over Arrows.
8+||| an (incomplete?) list of birds introduced.
109
1110module Data.Combinators
1211
libs/contrib/Data/PosNat.idrnew file+39
@@ -0,0 +1,39 @@
1+module Data.PosNat
2+
3+import Data.So
4+
5+%default total
6+%access public export
7+
8+||| ℤ⁺
9+PosNat : Type
10+PosNat = DPair Nat IsSucc
11+
12+||| A proof that
13+plusPos : (n, k : Nat) -> IsSucc n -> IsSucc (n + k)
14+plusPos (S n) k pn = ItIsSucc
15+
16+plusPosNat : PosNat -> PosNat -> PosNat
17+plusPosNat (n ** pn) (k ** _) = (n + k ** plusPos n k pn)
18+
19+plusNatPosNat : Nat -> PosNat -> PosNat
20+plusNatPosNat n (S k ** pk) = (S $ k + n ** ItIsSucc)
21+
22+timesPos : (n, k : Nat) -> IsSucc n -> IsSucc k -> IsSucc (n * k)
23+timesPos n@(S _) k@(S _) pn pk = ItIsSucc
24+
25+multPosNat : PosNat -> PosNat -> PosNat
26+multPosNat (n ** pn) (k ** pk) = (n * k ** timesPos n k pn pk)
27+
28+one : PosNat
29+one = (1 ** ItIsSucc)
30+
31+succ : PosNat -> PosNat
32+succ (n ** _) = (S n ** ItIsSucc)
33+
34+Semigroup PosNat where
35+ (<+>) = plusPosNat
36+
37+p : (n : Nat) -> {auto ok : IsSucc n} -> PosNat
38+p Z {ok} impossible
39+p k {ok} = (k ** ok)
libs/contrib/Data/SortedBag.idrnew file+123
@@ -0,0 +1,123 @@
1+module Data.SortedBag
2+
3+import Control.Isomorphism
4+import Control.Pipeline
5+import Data.Chain
6+import Data.Combinators
7+import Data.PosNat
8+import Data.SortedMap
9+
10+%default total
11+%access export
12+
13+data SortedBag k = BagWrapper (SortedMap k PosNat)
14+
15+||| Remove the `BagWrapper` from a bag (the required proof from `PosNat` makes
16+||| this safe)
17+unwrapBag : SortedBag k -> SortedMap k PosNat
18+unwrapBag (BagWrapper m) = m
19+
20+||| An `Isomorphism` between a wrapped and unwrapped bag
21+wrappedBagIso : Iso (SortedMap k PosNat) (SortedBag k)
22+wrappedBagIso = MkIso BagWrapper unwrapBag (\(BagWrapper _) => Refl) (\_ => Refl)
23+
24+||| A type for converting a function from an operation over SortedMaps to an
25+||| operation over SortedBags
26+OnMapsT : Nat -> Type -> Type
27+OnMapsT n k = (EndoChain n $ SortedMap k PosNat) -> (EndoChain n $ SortedBag k)
28+
29+||| Apply an n-ary function over the wrapped `SortedMap`.
30+onMaps : OnMapsT n k
31+onMaps = withIso wrappedBagIso
32+
33+||| Special case for n=1 for `onMaps`
34+onMap : OnMapsT 1 k
35+onMap = onMaps {n=1}
36+
37+||| An empty bag.
38+empty : Ord k => SortedBag k
39+empty = BagWrapper empty
40+
41+-- Keep in mind:
42+-- Idris> the Nat $ sum Nothing
43+-- 0 : Nat
44+-- Idris> the Nat $ sum $ Just 10
45+-- 10 : Nat
46+
47+||| The type of `insert` and the common core of most functions that update
48+||| the contests of a Bag.
49+UpdateBag : Type -> Type
50+UpdateBag k = k -> SortedBag k -> SortedBag k
51+
52+||| Apply a function `(Nat -> Nat)` to a given argument
53+alterCounts : (Nat -> Nat) -> UpdateBag k
54+alterCounts f k = onMap $ \m => let
55+ n = sum $ fst <$> lookup k m
56+ n' = f n
57+ in m |> if n == n'
58+ then id -- No change before and after.
59+ else case n' of
60+ Z => delete k
61+ n'@(S _) => insert k (n' ** ItIsSucc)
62+
63+||| Count the number of occurances
64+count : k -> SortedBag k -> Nat
65+count k (BagWrapper m) = sum $ fst <$> lookup k m
66+
67+||| Is a count non-zero?
68+contains : k -> SortedBag k -> Bool
69+contains = isZero ... count
70+
71+||| insert a given number of items
72+insertN : Nat -> UpdateBag k
73+insertN n = alterCounts (plus n)
74+
75+||| insert a single item.
76+insert : UpdateBag k
77+insert = alterCounts S
78+
79+||| delete a given number of items
80+deleteN : Nat -> UpdateBag k
81+deleteN n = alterCounts (`minus` n)
82+
83+||| delete 1 item (equivalent to `deleteN 1`)
84+delete1 : UpdateBag k
85+delete1 = deleteN 1
86+
87+||| Delete all ocurances
88+delete : UpdateBag k
89+delete = alterCounts $ const Z
90+
91+||| A single item (more efficient than `insert x empty`)
92+singleton : Ord k => k -> SortedBag k
93+singleton k = BagWrapper $ Data.SortedMap.insert k one empty
94+-- So that we don't need to do a fetch first
95+
96+-- The reason for rewriting this file, because now it is
97+||| O(1). Are there any items? The proof in PosNat ensures that there are no
98+||| zero-counted items.
99+null : SortedBag k -> Bool
100+null (BagWrapper m) = null m
101+
102+||| Convert a list to a Sorted Bag
103+fromList : Ord k => List k -> SortedBag k
104+fromList = foldr insert empty
105+
106+||| Convert a Sorted Bag to a List, keeping it sorted.
107+toList : SortedBag k -> List k
108+toList (BagWrapper m) = concat $ (\(x, (n ** _)) => replicate n x) <$> toList m
109+
110+-- TODO: more efficient, implementation also for Map and Set
111+Foldable SortedBag where
112+ foldl f zero = foldl f zero . Data.SortedBag.toList
113+ foldr f zero = foldr f zero . Data.SortedBag.toList
114+
115+||| Merge two bags
116+union : EndoChain 2 (SortedBag k)
117+union = onMaps {n=2} merge
118+
119+Semigroup (SortedBag a) where
120+ (<+>) = union
121+
122+Ord a => Monoid (SortedBag a) where
123+ neutral = empty
libs/contrib/Data/SortedMap.idr+5
@@ -249,6 +249,11 @@ export
249249values : SortedMap k v -> List v
250250values = map snd . toList
251251
252+export
253+null : SortedMap k v -> Bool
254+null Empty = True
255+null (M _ _) = False
256+
252257treeMap : (a -> b) -> Tree n k a o -> Tree n k b o
253258treeMap f (Leaf k v) = Leaf k (f v)
254259treeMap f (Branch2 t1 k t2) = Branch2 (treeMap f t1) k (treeMap f t2)
libs/contrib/contrib.ipkg+3
@@ -25,6 +25,7 @@ modules = CFFI
2525
2626 , Data.Bool.Extra
2727 , Data.BoundedList
28+ , Data.Chain
2829 , Data.CoList
2930 , Data.Combinators
3031 , Data.Combinators.Applicative
@@ -47,8 +48,10 @@ modules = CFFI
4748 , Data.Nat.DivMod.IteratedSubtraction
4849
4950 , Data.Pairs.Implicit
51+ , Data.PosNat
5052 , Data.Rel
5153 , Data.Sign
54+ , Data.SortedBag
5255 , Data.SortedMap
5356 , Data.SortedSet
5457 , Data.Storable