mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-18 05:42:09 +01:00
fn: add uncons, unsnoc and its component projections
This commit is contained in:
parent
9f0cc159ea
commit
4e1579cf4c
60
fn/slice.go
60
fn/slice.go
@ -258,3 +258,63 @@ func ForEachConc[A, B any](f func(A) B,
|
||||
|
||||
return bs
|
||||
}
|
||||
|
||||
// Head returns the first element of the slice, assuming it is non-empty.
|
||||
func Head[A any](items []A) Option[A] {
|
||||
if len(items) == 0 {
|
||||
return None[A]()
|
||||
}
|
||||
|
||||
return Some(items[0])
|
||||
}
|
||||
|
||||
// Tail returns the slice without the first element, assuming the slice is not
|
||||
// empty. Note this makes a copy of the slice.
|
||||
func Tail[A any](items []A) Option[[]A] {
|
||||
if len(items) == 0 {
|
||||
return None[[]A]()
|
||||
}
|
||||
|
||||
res := make([]A, len(items)-1)
|
||||
copy(res, items[1:])
|
||||
|
||||
return Some(res)
|
||||
}
|
||||
|
||||
// Init returns the slice without the last element, assuming the slice is not
|
||||
// empty. Note this makes a copy of the slice.
|
||||
func Init[A any](items []A) Option[[]A] {
|
||||
if len(items) == 0 {
|
||||
return None[[]A]()
|
||||
}
|
||||
|
||||
res := make([]A, len(items)-1)
|
||||
copy(res, items[0:len(items)-1])
|
||||
|
||||
return Some(res)
|
||||
}
|
||||
|
||||
// Last returns the last element of the slice, assuming it is non-empty.
|
||||
func Last[A any](items []A) Option[A] {
|
||||
if len(items) == 0 {
|
||||
return None[A]()
|
||||
}
|
||||
|
||||
return Some(items[len(items)-1])
|
||||
}
|
||||
|
||||
// Uncons splits a slice into a pair of its Head and Tail.
|
||||
func Uncons[A any](items []A) Option[T2[A, []A]] {
|
||||
return LiftA2Option(NewT2[A, []A])(Head(items), Tail(items))
|
||||
}
|
||||
|
||||
// Unsnoc splits a slice into a pair of its Init and Last.
|
||||
func Unsnoc[A any](items []A) Option[T2[[]A, A]] {
|
||||
return LiftA2Option(NewT2[[]A, A])(Init(items), Last(items))
|
||||
}
|
||||
|
||||
// Len is the len function that is defined in a way that makes it usable in
|
||||
// higher-order contexts.
|
||||
func Len[A any](items []A) uint {
|
||||
return uint(len(items))
|
||||
}
|
||||
|
@ -374,3 +374,61 @@ func TestPropFindIdxFindIdentity(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPropLastTailIsLast(t *testing.T) {
|
||||
f := func(s []uint8) bool {
|
||||
// We exclude the singleton case because the Tail is empty.
|
||||
if len(s) <= 1 {
|
||||
return true
|
||||
}
|
||||
|
||||
return Last(s) == ChainOption(Last[uint8])(Tail(s))
|
||||
}
|
||||
|
||||
require.NoError(t, quick.Check(f, nil))
|
||||
}
|
||||
|
||||
func TestPropHeadInitIsHead(t *testing.T) {
|
||||
f := func(s []uint8) bool {
|
||||
// We exclude the singleton case because the Init is empty.
|
||||
if len(s) <= 1 {
|
||||
return true
|
||||
}
|
||||
|
||||
return Head(s) == ChainOption(Head[uint8])(Init(s))
|
||||
}
|
||||
|
||||
require.NoError(t, quick.Check(f, nil))
|
||||
}
|
||||
|
||||
func TestPropTailDecrementsLength(t *testing.T) {
|
||||
f := func(s []uint8) bool {
|
||||
if len(s) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return Some(Len(s)-1) == MapOption(Len[uint8])(Tail(s))
|
||||
}
|
||||
|
||||
require.NoError(t, quick.Check(f, nil))
|
||||
}
|
||||
|
||||
func TestPropInitDecrementsLength(t *testing.T) {
|
||||
f := func(s []uint8) bool {
|
||||
if len(s) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return Some(Len(s)-1) == MapOption(Len[uint8])(Init(s))
|
||||
}
|
||||
|
||||
require.NoError(t, quick.Check(f, nil))
|
||||
}
|
||||
|
||||
func TestSingletonTailIsEmpty(t *testing.T) {
|
||||
require.Equal(t, Tail([]int{1}), Some([]int{}))
|
||||
}
|
||||
|
||||
func TestSingletonInitIsEmpty(t *testing.T) {
|
||||
require.Equal(t, Init([]int{1}), Some([]int{}))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user