Import NonEmpty/
This commit is contained in:
parent
182738f0fb
commit
8fc7b60c0e
20 changed files with 528 additions and 0 deletions
9
NonEmpty/Type.dhall
Normal file
9
NonEmpty/Type.dhall
Normal file
|
@ -0,0 +1,9 @@
|
|||
{-|
|
||||
A `NonEmpty` list has at least one element and supports many of the same
|
||||
operations as `List`s
|
||||
-}
|
||||
let NonEmpty
|
||||
: Type → Type
|
||||
= λ(a : Type) → { head : a, tail : List a }
|
||||
|
||||
in NonEmpty
|
28
NonEmpty/all.dhall
Normal file
28
NonEmpty/all.dhall
Normal file
|
@ -0,0 +1,28 @@
|
|||
{-|
|
||||
Returns `True` if the supplied function returns `True` for all elements in the
|
||||
`NonEmpty` list
|
||||
-}
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let NonEmpty/toList = ./toList.dhall
|
||||
|
||||
let all
|
||||
: ∀(a : Type) → (a → Bool) → NonEmpty a → Bool
|
||||
= λ(a : Type) →
|
||||
λ(f : a → Bool) →
|
||||
λ(xs : NonEmpty a) →
|
||||
List/fold
|
||||
a
|
||||
(NonEmpty/toList a xs)
|
||||
Bool
|
||||
(λ(x : a) → λ(r : Bool) → f x && r)
|
||||
True
|
||||
|
||||
let example0 =
|
||||
assert : all Natural Natural/even { head = 2, tail = [ 3, 5 ] } ≡ False
|
||||
|
||||
let example1 =
|
||||
assert
|
||||
: all Natural Natural/even { head = 2, tail = [] : List Natural } ≡ True
|
||||
|
||||
in all
|
28
NonEmpty/any.dhall
Normal file
28
NonEmpty/any.dhall
Normal file
|
@ -0,0 +1,28 @@
|
|||
{-|
|
||||
Returns `True` if the supplied function returns `True` for any element in the
|
||||
`NonEmpty` list
|
||||
-}
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let NonEmpty/toList = ./toList.dhall
|
||||
|
||||
let any
|
||||
: ∀(a : Type) → (a → Bool) → NonEmpty a → Bool
|
||||
= λ(a : Type) →
|
||||
λ(f : a → Bool) →
|
||||
λ(xs : NonEmpty a) →
|
||||
List/fold
|
||||
a
|
||||
(NonEmpty/toList a xs)
|
||||
Bool
|
||||
(λ(x : a) → λ(r : Bool) → f x || r)
|
||||
False
|
||||
|
||||
let example0 =
|
||||
assert : any Natural Natural/even { head = 2, tail = [ 3, 5 ] } ≡ True
|
||||
|
||||
let example1 =
|
||||
assert
|
||||
: any Natural Natural/even { head = 3, tail = [] : List Natural } ≡ False
|
||||
|
||||
in any
|
52
NonEmpty/concat.dhall
Normal file
52
NonEmpty/concat.dhall
Normal file
|
@ -0,0 +1,52 @@
|
|||
{-|
|
||||
Concatenate a `NonEmpty` list of `NonEmpty` lists into a single `NonEmpty`
|
||||
list
|
||||
-}
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let NonEmpty/toList = ./toList.dhall
|
||||
|
||||
let List/concatMap = ../List/concatMap.dhall
|
||||
|
||||
let concat
|
||||
: ∀(a : Type) → NonEmpty (NonEmpty a) → NonEmpty a
|
||||
= λ(a : Type) →
|
||||
λ(xss : NonEmpty (NonEmpty a)) →
|
||||
{ head = xss.head.head
|
||||
, tail =
|
||||
xss.head.tail
|
||||
# List/concatMap (NonEmpty a) a (NonEmpty/toList a) xss.tail
|
||||
}
|
||||
|
||||
let example0 =
|
||||
assert
|
||||
: concat
|
||||
Natural
|
||||
{ head = { head = 0, tail = [ 1, 2 ] }
|
||||
, tail =
|
||||
[ { head = 3, tail = [ 4 ] }, { head = 5, tail = [ 6, 7, 8 ] } ]
|
||||
}
|
||||
≡ { head = 0, tail = [ 1, 2, 3, 4, 5, 6, 7, 8 ] }
|
||||
|
||||
let example1 =
|
||||
assert
|
||||
: concat
|
||||
Natural
|
||||
{ head = { head = 0, tail = [] : List Natural }
|
||||
, tail =
|
||||
[ { head = 1, tail = [] : List Natural }
|
||||
, { head = 2, tail = [] : List Natural }
|
||||
]
|
||||
}
|
||||
≡ { head = 0, tail = [ 1, 2 ] : List Natural }
|
||||
|
||||
let example2 =
|
||||
assert
|
||||
: concat
|
||||
Natural
|
||||
{ head = { head = 0, tail = [] : List Natural }
|
||||
, tail = [] : List (NonEmpty Natural)
|
||||
}
|
||||
≡ { head = 0, tail = [] : List Natural }
|
||||
|
||||
in concat
|
47
NonEmpty/concatMap.dhall
Normal file
47
NonEmpty/concatMap.dhall
Normal file
|
@ -0,0 +1,47 @@
|
|||
{-|
|
||||
Transform a `NonEmpty` list by applying a function to each element and
|
||||
flattening the results
|
||||
-}
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let NonEmpty/toList = ./toList.dhall
|
||||
|
||||
let List/concatMap = ../List/concatMap.dhall
|
||||
|
||||
let concatMap
|
||||
: ∀(a : Type) → ∀(b : Type) → (a → NonEmpty b) → NonEmpty a → NonEmpty b
|
||||
= λ(a : Type) →
|
||||
λ(b : Type) →
|
||||
λ(f : a → NonEmpty b) →
|
||||
λ(xs : NonEmpty a) →
|
||||
let ys = f xs.head
|
||||
|
||||
in { head = ys.head
|
||||
, tail =
|
||||
ys.tail
|
||||
# List/concatMap
|
||||
a
|
||||
b
|
||||
(λ(x : a) → NonEmpty/toList b (f x))
|
||||
xs.tail
|
||||
}
|
||||
|
||||
let example0 =
|
||||
assert
|
||||
: concatMap
|
||||
Natural
|
||||
Natural
|
||||
(λ(n : Natural) → { head = n, tail = [ n ] })
|
||||
{ head = 2, tail = [ 3, 5 ] }
|
||||
≡ { head = 2, tail = [ 2, 3, 3, 5, 5 ] }
|
||||
|
||||
let example1 =
|
||||
assert
|
||||
: concatMap
|
||||
Natural
|
||||
Natural
|
||||
(λ(n : Natural) → { head = n, tail = [ n ] })
|
||||
{ head = 2, tail = [] : List Natural }
|
||||
≡ { head = 2, tail = [ 2 ] }
|
||||
|
||||
in concatMap
|
10
NonEmpty/head.dhall
Normal file
10
NonEmpty/head.dhall
Normal file
|
@ -0,0 +1,10 @@
|
|||
--| Retrieve the first element of the `NonEmpty` list
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let head
|
||||
: ∀(a : Type) → NonEmpty a → a
|
||||
= λ(a : Type) → λ(xs : NonEmpty a) → xs.head
|
||||
|
||||
let example = assert : head Natural { head = 0, tail = [ 1, 2 ] } ≡ 0
|
||||
|
||||
in head
|
27
NonEmpty/index.dhall
Normal file
27
NonEmpty/index.dhall
Normal file
|
@ -0,0 +1,27 @@
|
|||
--| Retrieve an element from a `NonEmpty` list using its 0-based index
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let List/index = ../List/index.dhall
|
||||
|
||||
let index
|
||||
: Natural → ∀(a : Type) → NonEmpty a → Optional a
|
||||
= λ(n : Natural) →
|
||||
λ(a : Type) →
|
||||
λ(xs : NonEmpty a) →
|
||||
if Natural/isZero n
|
||||
then Some xs.head
|
||||
else List/index (Natural/subtract 1 n) a xs.tail
|
||||
|
||||
let property =
|
||||
λ(n : Natural) →
|
||||
λ(a : Type) →
|
||||
λ(xs : NonEmpty a) →
|
||||
assert : index 0 a xs ≡ Some xs.head
|
||||
|
||||
let example0 = assert : index 1 Natural { head = 2, tail = [ 3, 5 ] } ≡ Some 3
|
||||
|
||||
let example1 =
|
||||
assert
|
||||
: index 1 Natural { head = 2, tail = [] : List Natural } ≡ None Natural
|
||||
|
||||
in index
|
35
NonEmpty/indexed.dhall
Normal file
35
NonEmpty/indexed.dhall
Normal file
|
@ -0,0 +1,35 @@
|
|||
--| Tag each element of the `NonEmpty` list with its index
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let List/map = ../List/map.dhall
|
||||
|
||||
let indexed
|
||||
: ∀(a : Type) → NonEmpty a → NonEmpty { index : Natural, value : a }
|
||||
= λ(a : Type) →
|
||||
λ(xs : NonEmpty a) →
|
||||
{ head = { index = 0, value = xs.head }
|
||||
, tail =
|
||||
List/map
|
||||
{ index : Natural, value : a }
|
||||
{ index : Natural, value : a }
|
||||
( λ(ix : { index : Natural, value : a }) →
|
||||
{ index = ix.index + 1, value = ix.value }
|
||||
)
|
||||
(List/indexed a xs.tail)
|
||||
}
|
||||
|
||||
let example0 =
|
||||
assert
|
||||
: indexed Bool { head = True, tail = [ False, True ] }
|
||||
≡ { head = { index = 0, value = True }
|
||||
, tail = [ { index = 1, value = False }, { index = 2, value = True } ]
|
||||
}
|
||||
|
||||
let example1 =
|
||||
assert
|
||||
: indexed Bool { head = True, tail = [] : List Bool }
|
||||
≡ { head = { index = 0, value = True }
|
||||
, tail = [] : List { index : Natural, value : Bool }
|
||||
}
|
||||
|
||||
in indexed
|
12
NonEmpty/last.dhall
Normal file
12
NonEmpty/last.dhall
Normal file
|
@ -0,0 +1,12 @@
|
|||
λ(nix : ../NixPrelude.dhall) →
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let Optional/default = ../Optional/default.dhall nix
|
||||
|
||||
let last
|
||||
: ∀(a : Type) → NonEmpty a → a
|
||||
= λ(a : Type) →
|
||||
λ(xs : NonEmpty a) →
|
||||
Optional/default a xs.head (List/last a xs.tail)
|
||||
|
||||
in last
|
13
NonEmpty/length.dhall
Normal file
13
NonEmpty/length.dhall
Normal file
|
@ -0,0 +1,13 @@
|
|||
--| Returns the number of elements in a `NonEmpty` list
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let length
|
||||
: ∀(a : Type) → NonEmpty a → Natural
|
||||
= λ(a : Type) → λ(xs : NonEmpty a) → List/length a xs.tail + 1
|
||||
|
||||
let example0 = assert : length Natural { head = 0, tail = [ 1, 2 ] } ≡ 3
|
||||
|
||||
let example1 =
|
||||
assert : length Natural { head = 0, tail = [] : List Natural } ≡ 1
|
||||
|
||||
in length
|
15
NonEmpty/make.dhall
Normal file
15
NonEmpty/make.dhall
Normal file
|
@ -0,0 +1,15 @@
|
|||
{-|
|
||||
Create a `NonEmpty` list using a function instead of a record
|
||||
|
||||
This might come in handy if you want to decouple the `NonEmpty` list
|
||||
construction from the specific names of the fields.
|
||||
-}
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let make
|
||||
: ∀(a : Type) → ∀(head : a) → ∀(tail : List a) → NonEmpty a
|
||||
= λ(a : Type) → λ(head : a) → λ(tail : List a) → { head, tail }
|
||||
|
||||
let example = assert : make Natural 1 [ 2, 3 ] ≡ { head = 1, tail = [ 2, 3 ] }
|
||||
|
||||
in make
|
24
NonEmpty/map.dhall
Normal file
24
NonEmpty/map.dhall
Normal file
|
@ -0,0 +1,24 @@
|
|||
--| Transform a `NonEmpty` list by applying a function to each element
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let List/map = ../List/map.dhall
|
||||
|
||||
let map
|
||||
: ∀(a : Type) → ∀(b : Type) → (a → b) → NonEmpty a → NonEmpty b
|
||||
= λ(a : Type) →
|
||||
λ(b : Type) →
|
||||
λ(f : a → b) →
|
||||
λ(xs : NonEmpty a) →
|
||||
{ head = f xs.head, tail = List/map a b f xs.tail }
|
||||
|
||||
let example0 =
|
||||
assert
|
||||
: map Natural Bool Natural/even { head = 2, tail = [ 3, 5 ] }
|
||||
≡ { head = True, tail = [ False, False ] }
|
||||
|
||||
let example1 =
|
||||
assert
|
||||
: map Natural Bool Natural/even { head = 2, tail = [] : List Natural }
|
||||
≡ { head = True, tail = [] : List Bool }
|
||||
|
||||
in map
|
20
NonEmpty/package.dhall
Normal file
20
NonEmpty/package.dhall
Normal file
|
@ -0,0 +1,20 @@
|
|||
λ(nix : ../NixPrelude.dhall) →
|
||||
{ Type = ./Type.dhall
|
||||
, all = ./all.dhall
|
||||
, any = ./any.dhall
|
||||
, concat = ./concat.dhall
|
||||
, concatMap = ./concatMap.dhall
|
||||
, head = ./head.dhall
|
||||
, index = ./index.dhall
|
||||
, indexed = ./indexed.dhall
|
||||
, last = ./last.dhall nix
|
||||
, length = ./length.dhall
|
||||
, make = ./make.dhall
|
||||
, map = ./map.dhall
|
||||
, reverse = ./reverse.dhall nix
|
||||
, shifted = ./shifted.dhall
|
||||
, singleton = ./singleton.dhall
|
||||
, toList = ./toList.dhall
|
||||
, unzip = ./unzip.dhall
|
||||
, zip = ./zip.dhall nix
|
||||
}
|
21
NonEmpty/reverse.dhall
Normal file
21
NonEmpty/reverse.dhall
Normal file
|
@ -0,0 +1,21 @@
|
|||
λ(nix : ../NixPrelude.dhall) →
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let List/drop = ../List/drop.dhall
|
||||
|
||||
let Optional/fold = ../Optional/fold.dhall nix
|
||||
|
||||
let reverse
|
||||
: ∀(a : Type) → NonEmpty a → NonEmpty a
|
||||
= λ(a : Type) →
|
||||
λ(xs : NonEmpty a) →
|
||||
let ys = List/reverse a xs.tail
|
||||
|
||||
in Optional/fold
|
||||
a
|
||||
(List/head a ys)
|
||||
(NonEmpty a)
|
||||
(λ(y : a) → { head = y, tail = List/drop 1 a ys # [ xs.head ] })
|
||||
{ head = xs.head, tail = [] : List a }
|
||||
|
||||
in reverse
|
89
NonEmpty/shifted.dhall
Normal file
89
NonEmpty/shifted.dhall
Normal file
|
@ -0,0 +1,89 @@
|
|||
{-|
|
||||
Combine a `NonEmpty` list of `NonEmpty` lists, offsetting the `index` of each
|
||||
element by the number of elements in preceding lists
|
||||
-}
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let NonEmpty/toList = ./toList.dhall
|
||||
|
||||
let List/map = ../List/map.dhall
|
||||
|
||||
let List/shifted = ../List/shifted.dhall
|
||||
|
||||
let shifted
|
||||
: ∀(a : Type) →
|
||||
NonEmpty (NonEmpty { index : Natural, value : a }) →
|
||||
NonEmpty { index : Natural, value : a }
|
||||
= λ(a : Type) →
|
||||
λ(kvss : NonEmpty (NonEmpty { index : Natural, value : a })) →
|
||||
{ head = kvss.head.head
|
||||
, tail =
|
||||
List/shifted
|
||||
a
|
||||
( [ kvss.head.tail ]
|
||||
# List/map
|
||||
(NonEmpty { index : Natural, value : a })
|
||||
(List { index : Natural, value : a })
|
||||
( λ(kvs : NonEmpty { index : Natural, value : a }) →
|
||||
List/map
|
||||
{ index : Natural, value : a }
|
||||
{ index : Natural, value : a }
|
||||
( λ(kv : { index : Natural, value : a }) →
|
||||
{ index = kv.index + 1, value = kv.value }
|
||||
)
|
||||
(NonEmpty/toList { index : Natural, value : a } kvs)
|
||||
)
|
||||
kvss.tail
|
||||
)
|
||||
}
|
||||
|
||||
let example0 =
|
||||
assert
|
||||
: shifted
|
||||
Bool
|
||||
{ head =
|
||||
{ head = { index = 0, value = True }
|
||||
, tail =
|
||||
[ { index = 1, value = True }, { index = 2, value = True } ]
|
||||
}
|
||||
, tail =
|
||||
[ { head = { index = 0, value = False }
|
||||
, tail = [ { index = 1, value = False } ]
|
||||
}
|
||||
, { head = { index = 0, value = True }
|
||||
, tail =
|
||||
[ { index = 1, value = True }
|
||||
, { index = 2, value = True }
|
||||
, { index = 3, value = True }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
≡ { head = { index = 0, value = True }
|
||||
, tail =
|
||||
[ { index = 1, value = True }
|
||||
, { index = 2, value = True }
|
||||
, { index = 3, value = False }
|
||||
, { index = 4, value = False }
|
||||
, { index = 5, value = True }
|
||||
, { index = 6, value = True }
|
||||
, { index = 7, value = True }
|
||||
, { index = 8, value = True }
|
||||
]
|
||||
}
|
||||
|
||||
let example1 =
|
||||
assert
|
||||
: shifted
|
||||
Bool
|
||||
{ head =
|
||||
{ head = { index = 0, value = True }
|
||||
, tail = [] : List { index : Natural, value : Bool }
|
||||
}
|
||||
, tail = [] : List (NonEmpty { index : Natural, value : Bool })
|
||||
}
|
||||
≡ { head = { index = 0, value = True }
|
||||
, tail = [] : List { index : Natural, value : Bool }
|
||||
}
|
||||
|
||||
in shifted
|
11
NonEmpty/singleton.dhall
Normal file
11
NonEmpty/singleton.dhall
Normal file
|
@ -0,0 +1,11 @@
|
|||
--| Create a `NonEmpty` list with just one element
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let singleton
|
||||
: ∀(a : Type) → a → NonEmpty a
|
||||
= λ(a : Type) → λ(x : a) → { head = x, tail = [] : List a }
|
||||
|
||||
let example =
|
||||
assert : singleton Natural 2 ≡ { head = 2, tail = [] : List Natural }
|
||||
|
||||
in singleton
|
14
NonEmpty/toList.dhall
Normal file
14
NonEmpty/toList.dhall
Normal file
|
@ -0,0 +1,14 @@
|
|||
--| Convert a `NonEmpty` list into the equivalent `List`
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let toList
|
||||
: ∀(a : Type) → NonEmpty a → List a
|
||||
= λ(a : Type) → λ(xs : NonEmpty a) → [ xs.head ] # xs.tail
|
||||
|
||||
let example0 =
|
||||
assert : toList Natural { head = 2, tail = [ 3, 5 ] } ≡ [ 2, 3, 5 ]
|
||||
|
||||
let example1 =
|
||||
assert : toList Natural { head = 2, tail = [] : List Natural } ≡ [ 2 ]
|
||||
|
||||
in toList
|
52
NonEmpty/unzip.dhall
Normal file
52
NonEmpty/unzip.dhall
Normal file
|
@ -0,0 +1,52 @@
|
|||
--| Unzip a `NonEmpty` list into two separate `NonEmpty` lists
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let NonEmpty/map = ./map.dhall
|
||||
|
||||
let unzip
|
||||
: ∀(a : Type) →
|
||||
∀(b : Type) →
|
||||
NonEmpty { _1 : a, _2 : b } →
|
||||
{ _1 : NonEmpty a, _2 : NonEmpty b }
|
||||
= λ(a : Type) →
|
||||
λ(b : Type) →
|
||||
λ(xs : NonEmpty { _1 : a, _2 : b }) →
|
||||
{ _1 =
|
||||
NonEmpty/map
|
||||
{ _1 : a, _2 : b }
|
||||
a
|
||||
(λ(x : { _1 : a, _2 : b }) → x._1)
|
||||
xs
|
||||
, _2 =
|
||||
NonEmpty/map
|
||||
{ _1 : a, _2 : b }
|
||||
b
|
||||
(λ(x : { _1 : a, _2 : b }) → x._2)
|
||||
xs
|
||||
}
|
||||
|
||||
let example0 =
|
||||
assert
|
||||
: unzip
|
||||
Text
|
||||
Bool
|
||||
{ head = { _1 = "ABC", _2 = True }
|
||||
, tail = [ { _1 = "DEF", _2 = False }, { _1 = "GHI", _2 = True } ]
|
||||
}
|
||||
≡ { _1 = { head = "ABC", tail = [ "DEF", "GHI" ] }
|
||||
, _2 = { head = True, tail = [ False, True ] }
|
||||
}
|
||||
|
||||
let example1 =
|
||||
assert
|
||||
: unzip
|
||||
Text
|
||||
Bool
|
||||
{ head = { _1 = "ABC", _2 = True }
|
||||
, tail = [] : List { _1 : Text, _2 : Bool }
|
||||
}
|
||||
≡ { _1 = { head = "ABC", tail = [] : List Text }
|
||||
, _2 = { head = True, tail = [] : List Bool }
|
||||
}
|
||||
|
||||
in unzip
|
20
NonEmpty/zip.dhall
Normal file
20
NonEmpty/zip.dhall
Normal file
|
@ -0,0 +1,20 @@
|
|||
λ(nix : ../NixPrelude.dhall) →
|
||||
let NonEmpty = ./Type.dhall
|
||||
|
||||
let List/zip = ../List/zip.dhall nix
|
||||
|
||||
let zip
|
||||
: ∀(a : Type) →
|
||||
NonEmpty a →
|
||||
∀(b : Type) →
|
||||
NonEmpty b →
|
||||
NonEmpty { _1 : a, _2 : b }
|
||||
= λ(a : Type) →
|
||||
λ(xs : NonEmpty a) →
|
||||
λ(b : Type) →
|
||||
λ(ys : NonEmpty b) →
|
||||
{ head = { _1 = xs.head, _2 = ys.head }
|
||||
, tail = List/zip a xs.tail b ys.tail
|
||||
}
|
||||
|
||||
in zip
|
|
@ -9,6 +9,7 @@
|
|||
, Map = ./Map/package.dhall nix
|
||||
, Misc = ./Misc/package.dhall nix
|
||||
, Monoid = ./Monoid.dhall
|
||||
, NonNull = ./NonEmpty/package.dhall nix
|
||||
, Natural = ./Natural/package.dhall nix
|
||||
, Number = ./Number/package.dhall nix
|
||||
, Path = ./Path/package.dhall nix
|
||||
|
|
Loading…
Reference in a new issue