# First and Last

First[T] and Last[T] are data structures that keep track of, respectively, the earliest and latest instances of T that you’ve seen. First[T] works for any type T:

First(3) + First(2) + First(1)

First("a") + First("b") + First("c")

As does Last[T]:

Last(3) + Last(2) + Last(1)

Last("a") + Last("b") + Last("c")

## Algebraic Properties

First[T] and Last[T] are both non-commutative semigroups. For First[T], the + function keeps the left input, while Last[T]’s + implementation keeps the right input. For example, for First[T]:

val first1 = First(1) + First(3) == First(1)
// first1: Boolean = true

val first3 = First(3) + First(1) == First(3)
// first3: Boolean = true

assert(first1 && first3)

And for Last[T]:

val last3 = Last(1) + Last(3) == Last(3)
// last3: Boolean = true

val last1 = Last(3) + Last(1) == Last(1)
// last1: Boolean = true

assert(last3 && last1)

## Usage Examples

Let’s use First[T] and Last[T] to keep track of the first and last username that a Twitter user has followed over the lifetime of their account. First let’s define a type alias for Username:

To track First and Last simultaneously we’ll use a combinator. As discussed on the Product Algebra docs page, the Tuple2[A, B] semigroup works by separately combining its left and right elements. This means that we can use a pair - a (First[Username], Last[Username]) - to track both the oldest and most recent twitter username that we’ve seen.

(First(user), Last(user))

Now let’s “add” up a few of these pairs, using the semigroup. First, we’ll import Algebird’s Operators._, which will enrich any semigroup with a + method.

val follows = follow("sam") + follow("erik") + follow("oscar") + follow("kelley")