on master help sign in
Various additions to contrib (#4343)
2be6e6aPatrick Hilhorst
CHANGELOG.md+7−2
@@ -2,6 +2,11 @@
2
2
3+ REPL now prints an error message if program compiled by `:exec` terminates
3+ REPL now prints an error message if program compiled by `:exec` terminates
4 abnormally.
4 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.
5
10
6## Library Updates
11## Library Updates
7
12
@@ -42,7 +47,7 @@
42+ C FFI now supports pasting in any expression by prefixing it with '#', e.g.
47+ C FFI now supports pasting in any expression by prefixing it with '#', e.g.
43 ```idris
48 ```idris
44 intMax : IO Int
49 intMax : IO Int
45− intMax = foreign FFI_C "#INT_MAX" (IO Int)
50+ intMax = foreign FFI_C "#INT_MAX" (IO Int)
46 ```
51 ```
47+ The deprecated keywords `%assert_total`, `abstract`, and `[static]` have
52+ The deprecated keywords `%assert_total`, `abstract`, and `[static]` have
48 been removed as well as the use of "public" instead of "public export" to
53 been removed as well as the use of "public" instead of "public export" to
@@ -93,7 +98,7 @@
93+ Removed several deprecated items from the libraries shipped with Idris.
98+ Removed several deprecated items from the libraries shipped with Idris.
94+ Moved `abs` from the `Neg` interface into its own `Abs` interface. `Nat`
99+ Moved `abs` from the `Neg` interface into its own `Abs` interface. `Nat`
95 implements `Abs` with `abs = id`.
100 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
97 implemented by `Effect.File` in the effects package.
102 implemented by `Effect.File` in the effects package.
98
103
99## Tool Updates
104## Tool Updates
libs/contrib/Data/BoundedList.idr+14
@@ -76,6 +76,20 @@ implementation Functor (BoundedList n) where
76 map f [] = []
76 map f [] = []
77 map f (x :: xs) = f x :: map f xs
77 map f (x :: xs) = f x :: map f xs
78
78
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+
79--------------------------------------------------------------------------------
93--------------------------------------------------------------------------------
80-- Misc
94-- Misc
81--------------------------------------------------------------------------------
95--------------------------------------------------------------------------------
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 @@
5||| hasn't actually read). See
5||| hasn't actually read). See
6||| http://www.angelfire.com/tx4/cus/combinator/birds.html and
6||| http://www.angelfire.com/tx4/cus/combinator/birds.html and
7||| https://hackage.haskell.org/package/data-aviary-0.4.0/docs/Data-Aviary-Birds.html
7||| 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
8+||| an (incomplete?) list of birds introduced.
9−||| over Arrows.
10
9
11module Data.Combinators
10module Data.Combinators
12
11
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
249values : SortedMap k v -> List v
249values : SortedMap k v -> List v
250values = map snd . toList
250values = map snd . toList
251
251
252+export
253+null : SortedMap k v -> Bool
254+null Empty = True
255+null (M _ _) = False
256+
252treeMap : (a -> b) -> Tree n k a o -> Tree n k b o
257treeMap : (a -> b) -> Tree n k a o -> Tree n k b o
253treeMap f (Leaf k v) = Leaf k (f v)
258treeMap f (Leaf k v) = Leaf k (f v)
254treeMap f (Branch2 t1 k t2) = Branch2 (treeMap f t1) k (treeMap f t2)
259treeMap f (Branch2 t1 k t2) = Branch2 (treeMap f t1) k (treeMap f t2)
libs/contrib/contrib.ipkg+3
@@ -25,6 +25,7 @@ modules = CFFI
25
25
26 , Data.Bool.Extra
26 , Data.Bool.Extra
27 , Data.BoundedList
27 , Data.BoundedList
28+ , Data.Chain
28 , Data.CoList
29 , Data.CoList
29 , Data.Combinators
30 , Data.Combinators
30 , Data.Combinators.Applicative
31 , Data.Combinators.Applicative
@@ -47,8 +48,10 @@ modules = CFFI
47 , Data.Nat.DivMod.IteratedSubtraction
48 , Data.Nat.DivMod.IteratedSubtraction
48
49
49 , Data.Pairs.Implicit
50 , Data.Pairs.Implicit
51+ , Data.PosNat
50 , Data.Rel
52 , Data.Rel
51 , Data.Sign
53 , Data.Sign
54+ , Data.SortedBag
52 , Data.SortedMap
55 , Data.SortedMap
53 , Data.SortedSet
56 , Data.SortedSet
54 , Data.Storable
57 , Data.Storable