2020-08-04 22:03:18 +03:00
|
|
|
module Data.List1
|
|
|
|
|
2021-01-27 21:23:08 +03:00
|
|
|
import public Data.Zippable
|
2021-11-26 13:55:17 +03:00
|
|
|
import Control.Function
|
2021-01-27 21:23:08 +03:00
|
|
|
|
2020-08-04 22:03:18 +03:00
|
|
|
%default total
|
|
|
|
|
2020-09-22 17:07:40 +03:00
|
|
|
infixr 7 :::
|
|
|
|
|
2021-03-17 17:07:52 +03:00
|
|
|
||| Non-empty lists.
|
2020-08-04 22:03:18 +03:00
|
|
|
public export
|
|
|
|
record List1 a where
|
2020-09-22 17:07:40 +03:00
|
|
|
constructor (:::)
|
2020-08-04 22:03:18 +03:00
|
|
|
head : a
|
|
|
|
tail : List a
|
|
|
|
|
2021-01-26 13:39:16 +03:00
|
|
|
%name List1 xs, ys, zs
|
|
|
|
|
2020-09-22 17:07:40 +03:00
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- Basic functions
|
|
|
|
|
2021-05-14 19:35:21 +03:00
|
|
|
public export
|
|
|
|
fromList : List a -> Maybe (List1 a)
|
|
|
|
fromList [] = Nothing
|
|
|
|
fromList (x :: xs) = Just (x ::: xs)
|
|
|
|
|
2020-09-22 17:07:40 +03:00
|
|
|
public export
|
Remove linearity subtyping
It's disappointing to have to do this, but I think necessary because
various issue reports have shown it to be unsound (at least as far as
inference goes) and, at the very least, confusing. This patch brings us
back to the basic rules of QTT.
On the one hand, this makes the 1 multiplicity less useful, because it
means we can't flag arguments as being used exactly once which would be
useful for optimisation purposes as well as precision in the type. On
the other hand, it removes some complexity (and a hack) from
unification, and has the advantage of being correct! Also, I still
consider the 1 multiplicity an experiment.
We can still do interesting things like protocol state tracking, which
is my primary motivation at least.
Ideally, if the 1 multiplicity is going to be more generall useful,
we'll need some kind of way of doing multiplicity polymorphism in the
future. I don't think subtyping is the way (I've pretty much always come
to regret adding some form of subtyping).
Fixes #73 (and maybe some others).
2020-12-27 22:58:35 +03:00
|
|
|
singleton : (x : a) -> List1 a
|
2020-09-22 17:07:40 +03:00
|
|
|
singleton a = a ::: []
|
|
|
|
|
2021-03-17 17:07:52 +03:00
|
|
|
||| Forget that a list is non-empty.
|
|
|
|
public export
|
|
|
|
forget : List1 a -> List a
|
|
|
|
forget (x ::: xs) = x :: xs
|
|
|
|
|
2020-09-22 17:07:40 +03:00
|
|
|
export
|
|
|
|
last : List1 a -> a
|
|
|
|
last (x ::: xs) = loop x xs where
|
|
|
|
loop : a -> List a -> a
|
|
|
|
loop x [] = x
|
|
|
|
loop _ (x :: xs) = loop x xs
|
|
|
|
|
|
|
|
export
|
2021-03-17 17:07:52 +03:00
|
|
|
init : List1 a -> List a
|
|
|
|
init (x ::: xs) = loop x xs where
|
|
|
|
loop : a -> List a -> List a
|
|
|
|
loop x [] = []
|
|
|
|
loop x (y :: xs) = x :: loop y xs
|
2020-09-22 17:07:40 +03:00
|
|
|
|
2021-03-17 17:07:52 +03:00
|
|
|
export
|
|
|
|
foldr1By : (func : a -> b -> b) -> (map : a -> b) -> (l : List1 a) -> b
|
|
|
|
foldr1By f map (x ::: xs) = loop x xs where
|
2020-09-22 17:07:40 +03:00
|
|
|
loop : a -> List a -> b
|
2021-03-17 17:07:52 +03:00
|
|
|
loop x [] = map x
|
|
|
|
loop x (y :: xs) = f x (loop y xs)
|
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
2021-03-17 17:07:52 +03:00
|
|
|
foldl1By : (func : b -> a -> b) -> (map : a -> b) -> (l : List1 a) -> b
|
|
|
|
foldl1By f map (x ::: xs) = foldl f (map x) xs
|
2020-09-22 17:07:40 +03:00
|
|
|
|
|
|
|
export
|
2021-03-17 17:07:52 +03:00
|
|
|
foldr1 : (func : a -> a -> a) -> (l : List1 a) -> a
|
|
|
|
foldr1 f = foldr1By f id
|
2020-09-22 17:07:40 +03:00
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
2021-03-17 17:07:52 +03:00
|
|
|
foldl1 : (func : a -> a -> a) -> (l : List1 a) -> a
|
|
|
|
foldl1 f = foldl1By f id
|
2020-09-22 17:07:40 +03:00
|
|
|
|
2021-11-18 17:33:56 +03:00
|
|
|
public export
|
2021-11-18 04:36:55 +03:00
|
|
|
length : List1 a -> Nat
|
|
|
|
length (_ ::: xs) = S (length xs)
|
|
|
|
|
2020-09-22 17:07:40 +03:00
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- Append
|
2020-08-04 22:03:18 +03:00
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
Remove linearity subtyping
It's disappointing to have to do this, but I think necessary because
various issue reports have shown it to be unsound (at least as far as
inference goes) and, at the very least, confusing. This patch brings us
back to the basic rules of QTT.
On the one hand, this makes the 1 multiplicity less useful, because it
means we can't flag arguments as being used exactly once which would be
useful for optimisation purposes as well as precision in the type. On
the other hand, it removes some complexity (and a hack) from
unification, and has the advantage of being correct! Also, I still
consider the 1 multiplicity an experiment.
We can still do interesting things like protocol state tracking, which
is my primary motivation at least.
Ideally, if the 1 multiplicity is going to be more generall useful,
we'll need some kind of way of doing multiplicity polymorphism in the
future. I don't think subtyping is the way (I've pretty much always come
to regret adding some form of subtyping).
Fixes #73 (and maybe some others).
2020-12-27 22:58:35 +03:00
|
|
|
appendl : (xs : List1 a) -> (ys : List a) -> List1 a
|
2020-09-22 17:07:40 +03:00
|
|
|
appendl (x ::: xs) ys = x ::: xs ++ ys
|
2020-08-04 22:03:18 +03:00
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
2021-03-17 17:07:52 +03:00
|
|
|
(++) : (xs, ys : List1 a) -> List1 a
|
|
|
|
(++) xs ys = appendl xs (forget ys)
|
2020-08-04 22:03:18 +03:00
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
Remove linearity subtyping
It's disappointing to have to do this, but I think necessary because
various issue reports have shown it to be unsound (at least as far as
inference goes) and, at the very least, confusing. This patch brings us
back to the basic rules of QTT.
On the one hand, this makes the 1 multiplicity less useful, because it
means we can't flag arguments as being used exactly once which would be
useful for optimisation purposes as well as precision in the type. On
the other hand, it removes some complexity (and a hack) from
unification, and has the advantage of being correct! Also, I still
consider the 1 multiplicity an experiment.
We can still do interesting things like protocol state tracking, which
is my primary motivation at least.
Ideally, if the 1 multiplicity is going to be more generall useful,
we'll need some kind of way of doing multiplicity polymorphism in the
future. I don't think subtyping is the way (I've pretty much always come
to regret adding some form of subtyping).
Fixes #73 (and maybe some others).
2020-12-27 22:58:35 +03:00
|
|
|
lappend : (xs : List a) -> (ys : List1 a) -> List1 a
|
2020-08-04 22:03:18 +03:00
|
|
|
lappend [] ys = ys
|
2021-03-17 17:07:52 +03:00
|
|
|
lappend (x :: xs) ys = (x ::: xs) ++ ys
|
2020-09-22 17:07:40 +03:00
|
|
|
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- Cons/Snoc
|
|
|
|
|
|
|
|
public export
|
Remove linearity subtyping
It's disappointing to have to do this, but I think necessary because
various issue reports have shown it to be unsound (at least as far as
inference goes) and, at the very least, confusing. This patch brings us
back to the basic rules of QTT.
On the one hand, this makes the 1 multiplicity less useful, because it
means we can't flag arguments as being used exactly once which would be
useful for optimisation purposes as well as precision in the type. On
the other hand, it removes some complexity (and a hack) from
unification, and has the advantage of being correct! Also, I still
consider the 1 multiplicity an experiment.
We can still do interesting things like protocol state tracking, which
is my primary motivation at least.
Ideally, if the 1 multiplicity is going to be more generall useful,
we'll need some kind of way of doing multiplicity polymorphism in the
future. I don't think subtyping is the way (I've pretty much always come
to regret adding some form of subtyping).
Fixes #73 (and maybe some others).
2020-12-27 22:58:35 +03:00
|
|
|
cons : (x : a) -> (xs : List1 a) -> List1 a
|
2020-09-22 17:07:40 +03:00
|
|
|
cons x xs = x ::: forget xs
|
2020-08-04 22:03:18 +03:00
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
Remove linearity subtyping
It's disappointing to have to do this, but I think necessary because
various issue reports have shown it to be unsound (at least as far as
inference goes) and, at the very least, confusing. This patch brings us
back to the basic rules of QTT.
On the one hand, this makes the 1 multiplicity less useful, because it
means we can't flag arguments as being used exactly once which would be
useful for optimisation purposes as well as precision in the type. On
the other hand, it removes some complexity (and a hack) from
unification, and has the advantage of being correct! Also, I still
consider the 1 multiplicity an experiment.
We can still do interesting things like protocol state tracking, which
is my primary motivation at least.
Ideally, if the 1 multiplicity is going to be more generall useful,
we'll need some kind of way of doing multiplicity polymorphism in the
future. I don't think subtyping is the way (I've pretty much always come
to regret adding some form of subtyping).
Fixes #73 (and maybe some others).
2020-12-27 22:58:35 +03:00
|
|
|
snoc : (xs : List1 a) -> (x : a) -> List1 a
|
2021-03-17 17:07:52 +03:00
|
|
|
snoc xs x = xs ++ (singleton x)
|
2020-09-22 17:07:40 +03:00
|
|
|
|
2021-03-04 22:09:15 +03:00
|
|
|
public export
|
|
|
|
unsnoc : (xs : List1 a) -> (List a, a)
|
2021-07-26 17:41:56 +03:00
|
|
|
unsnoc (x ::: xs) = go x xs where
|
|
|
|
|
|
|
|
go : (x : a) -> (xs : List a) -> (List a, a)
|
|
|
|
go x [] = ([], x)
|
|
|
|
go x (y :: ys) = let (ini,lst) = go y ys
|
|
|
|
in (x :: ini, lst)
|
2021-03-04 22:09:15 +03:00
|
|
|
|
2020-09-22 17:07:40 +03:00
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- Reverse
|
|
|
|
|
|
|
|
public export
|
Remove linearity subtyping
It's disappointing to have to do this, but I think necessary because
various issue reports have shown it to be unsound (at least as far as
inference goes) and, at the very least, confusing. This patch brings us
back to the basic rules of QTT.
On the one hand, this makes the 1 multiplicity less useful, because it
means we can't flag arguments as being used exactly once which would be
useful for optimisation purposes as well as precision in the type. On
the other hand, it removes some complexity (and a hack) from
unification, and has the advantage of being correct! Also, I still
consider the 1 multiplicity an experiment.
We can still do interesting things like protocol state tracking, which
is my primary motivation at least.
Ideally, if the 1 multiplicity is going to be more generall useful,
we'll need some kind of way of doing multiplicity polymorphism in the
future. I don't think subtyping is the way (I've pretty much always come
to regret adding some form of subtyping).
Fixes #73 (and maybe some others).
2020-12-27 22:58:35 +03:00
|
|
|
reverseOnto : (acc : List1 a) -> (xs : List a) -> List1 a
|
2020-09-22 17:07:40 +03:00
|
|
|
reverseOnto acc [] = acc
|
|
|
|
reverseOnto acc (x :: xs) = reverseOnto (x ::: forget acc) xs
|
|
|
|
|
|
|
|
public export
|
Remove linearity subtyping
It's disappointing to have to do this, but I think necessary because
various issue reports have shown it to be unsound (at least as far as
inference goes) and, at the very least, confusing. This patch brings us
back to the basic rules of QTT.
On the one hand, this makes the 1 multiplicity less useful, because it
means we can't flag arguments as being used exactly once which would be
useful for optimisation purposes as well as precision in the type. On
the other hand, it removes some complexity (and a hack) from
unification, and has the advantage of being correct! Also, I still
consider the 1 multiplicity an experiment.
We can still do interesting things like protocol state tracking, which
is my primary motivation at least.
Ideally, if the 1 multiplicity is going to be more generall useful,
we'll need some kind of way of doing multiplicity polymorphism in the
future. I don't think subtyping is the way (I've pretty much always come
to regret adding some form of subtyping).
Fixes #73 (and maybe some others).
2020-12-27 22:58:35 +03:00
|
|
|
reverse : (xs : List1 a) -> List1 a
|
2020-09-22 17:07:40 +03:00
|
|
|
reverse (x ::: xs) = reverseOnto (singleton x) xs
|
|
|
|
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- Instances
|
2020-08-04 22:03:18 +03:00
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
2020-09-22 17:07:40 +03:00
|
|
|
Semigroup (List1 a) where
|
2021-03-17 17:07:52 +03:00
|
|
|
(<+>) = (++)
|
2020-08-04 22:03:18 +03:00
|
|
|
|
2021-03-01 11:29:43 +03:00
|
|
|
public export
|
2020-09-22 17:07:40 +03:00
|
|
|
Functor List1 where
|
|
|
|
map f (x ::: xs) = f x ::: map f xs
|
2020-08-04 22:03:18 +03:00
|
|
|
|
2021-03-01 11:29:43 +03:00
|
|
|
public export
|
2020-08-04 22:03:18 +03:00
|
|
|
Applicative List1 where
|
2020-09-22 17:07:40 +03:00
|
|
|
pure x = singleton x
|
|
|
|
f ::: fs <*> xs = appendl (map f xs) (fs <*> forget xs)
|
2020-08-04 22:03:18 +03:00
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
2020-08-04 22:03:18 +03:00
|
|
|
Monad List1 where
|
2020-09-22 17:07:40 +03:00
|
|
|
(x ::: xs) >>= f = appendl (f x) (xs >>= forget . f)
|
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
2020-09-22 17:07:40 +03:00
|
|
|
Foldable List1 where
|
|
|
|
foldr c n (x ::: xs) = c x (foldr c n xs)
|
2021-06-01 17:05:04 +03:00
|
|
|
foldl f z (x ::: xs) = foldl f (f z x) xs
|
2020-12-10 21:04:23 +03:00
|
|
|
null _ = False
|
2021-05-11 10:26:00 +03:00
|
|
|
toList = forget
|
2021-06-01 17:05:04 +03:00
|
|
|
foldMap f (x ::: xs) = f x <+> foldMap f xs
|
2020-09-22 17:07:40 +03:00
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
2020-12-21 06:46:14 +03:00
|
|
|
Traversable List1 where
|
|
|
|
traverse f (x ::: xs) = [| f x ::: traverse f xs |]
|
|
|
|
|
2020-09-22 17:07:40 +03:00
|
|
|
export
|
|
|
|
Show a => Show (List1 a) where
|
|
|
|
show = show . forget
|
2020-09-05 11:41:31 +03:00
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
2020-09-05 11:41:31 +03:00
|
|
|
Eq a => Eq (List1 a) where
|
2020-09-22 17:07:40 +03:00
|
|
|
(x ::: xs) == (y ::: ys) = x == y && xs == ys
|
2020-09-05 11:41:31 +03:00
|
|
|
|
2022-03-18 11:40:37 +03:00
|
|
|
public export
|
2020-09-05 11:41:31 +03:00
|
|
|
Ord a => Ord (List1 a) where
|
2020-09-22 17:07:40 +03:00
|
|
|
compare xs ys = compare (forget xs) (forget ys)
|
|
|
|
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
-- Properties
|
2020-09-05 11:41:31 +03:00
|
|
|
|
|
|
|
export
|
2021-06-28 14:49:33 +03:00
|
|
|
consInjective : (x ::: xs) === (y ::: ys) -> (x === y, xs === ys)
|
2020-09-05 11:41:31 +03:00
|
|
|
consInjective Refl = (Refl, Refl)
|
2021-01-26 13:39:16 +03:00
|
|
|
|
2021-11-26 13:55:17 +03:00
|
|
|
export
|
|
|
|
{x : a} -> Injective (x :::) where
|
|
|
|
injective Refl = Refl
|
|
|
|
|
|
|
|
export
|
|
|
|
{ys : List a} -> Injective (::: ys) where
|
|
|
|
injective Refl = Refl
|
|
|
|
|
2022-02-07 20:51:04 +03:00
|
|
|
||| Proof that the length of a List1 is the same as the length
|
|
|
|
||| of the List it represents.
|
|
|
|
export
|
|
|
|
listLength : (xs : List1 a) -> length xs = length (forget xs)
|
|
|
|
listLength (head ::: tail) = Refl
|
|
|
|
|
2021-01-26 13:39:16 +03:00
|
|
|
------------------------------------------------------------------------
|
2021-01-27 21:23:08 +03:00
|
|
|
-- Zippable
|
2021-01-26 13:39:16 +03:00
|
|
|
|
2021-03-01 11:29:17 +03:00
|
|
|
public export
|
2021-01-27 21:23:08 +03:00
|
|
|
Zippable List1 where
|
|
|
|
zipWith f (x ::: xs) (y ::: ys) = f x y ::: zipWith' xs ys
|
2021-01-26 13:39:16 +03:00
|
|
|
where
|
2021-01-27 21:23:08 +03:00
|
|
|
zipWith' : List a -> List b -> List c
|
|
|
|
zipWith' [] _ = []
|
|
|
|
zipWith' _ [] = []
|
|
|
|
zipWith' (x :: xs) (y :: ys) = f x y :: zipWith' xs ys
|
|
|
|
|
|
|
|
zipWith3 f (x ::: xs) (y ::: ys) (z ::: zs) = f x y z ::: zipWith3' xs ys zs
|
|
|
|
where
|
|
|
|
zipWith3' : List a -> List b -> List c -> List d
|
|
|
|
zipWith3' [] _ _ = []
|
|
|
|
zipWith3' _ [] _ = []
|
|
|
|
zipWith3' _ _ [] = []
|
|
|
|
zipWith3' (x :: xs) (y :: ys) (z :: zs) = f x y z :: zipWith3' xs ys zs
|
|
|
|
|
|
|
|
unzipWith f (x ::: xs) = let (b, c) = f x
|
2021-01-26 13:39:16 +03:00
|
|
|
(bs, cs) = unzipWith' xs in
|
2021-01-27 21:23:08 +03:00
|
|
|
(b ::: bs, c ::: cs)
|
|
|
|
where
|
|
|
|
unzipWith' : List a -> (List b, List c)
|
|
|
|
unzipWith' [] = ([], [])
|
|
|
|
unzipWith' (x :: xs) = let (b, c) = f x
|
|
|
|
(bs, cs) = unzipWith' xs in
|
|
|
|
(b :: bs, c :: cs)
|
|
|
|
|
|
|
|
unzipWith3 f (x ::: xs) = let (b, c, d) = f x
|
2021-01-26 13:39:16 +03:00
|
|
|
(bs, cs, ds) = unzipWith3' xs in
|
2021-01-27 21:23:08 +03:00
|
|
|
(b ::: bs, c ::: cs, d ::: ds)
|
|
|
|
where
|
|
|
|
unzipWith3' : List a -> (List b, List c, List d)
|
|
|
|
unzipWith3' [] = ([], [], [])
|
|
|
|
unzipWith3' (x :: xs) = let (b, c, d) = f x
|
|
|
|
(bs, cs, ds) = unzipWith3' xs in
|
|
|
|
(b :: bs, c :: cs, d :: ds)
|
2021-05-31 20:23:45 +03:00
|
|
|
|
|
|
|
export
|
|
|
|
Uninhabited a => Uninhabited (List1 a) where
|
|
|
|
uninhabited (hd ::: _) = uninhabited hd
|