Implements
Setoid
, Semigroup
, Monoid
Last a = Last (Maybe a)
Last
is a Monoid
that will always return the last, non-empty value when two Last
instances are combined. Last
is able to be a Monoid
because it implements a Maybe
under the hood. The use of the Maybe
allows for anempty
Last
to be represented with a Nothing
.
Last
can be constructed with either a value or a Maybe
instance. Any value passed to the constructor will be wrapped in a Just
to represent a non-empty instance of Last
. Any Maybe
passed to the constructor will be lifted as is, allowing the ability to "choose" a value based on some disjunction.
While most Monoid
s only provide a valueOf
function used for extraction, Last
takes advantage of its underlying Maybe
to provide an additional option
method. Using valueOf
will extract the underlying Maybe
, while option
will extract the underlying value in the Maybe
, using the provided default value when the underlyingMaybe
is a Nothing
instance.
import Last from 'crocks/Last'
import and from 'crocks/logic/and'
import isNumber from 'crocks/predicates/isNumber'
import mconcatMap from 'crocks/helpers/mconcatMap'
import safe from 'crocks/Maybe/safe'
// isEven :: Number -> Boolean
const isEven =
x => x % 2 === 0
// isValid :: a -> Boolean
const isValid =
and(isNumber, isEven)
// chooseLast :: [ * ] -> Last Number
const chooseLast =
mconcatMap(Last, safe(isValid))
chooseLast([ 21, 45, 2, 22, 19 ])
.valueOf()
//=> Just 22
chooseLast([ 'a', 'b', 'c' ])
.option('')
//=> ""
Setoid
, Semigroup
, Monoid
Last :: a -> Last (Maybe a)
Last :: Maybe a -> Last (Maybe a)
A Last
instance can be constructed by passing either a direct (unwrapped) value a
or a Maybe a
to the constructor. When a direct value is passed, the constructor will always wrap the value in a Just
and return a new Last Just a
instance.
Alternatively, by passing a Maybe a
, the user can programmatically provide an empty case to a given Last
by passing a Nothing
.
import Last from 'crocks/Last'
import Maybe from 'crocks/Maybe'
const { Just, Nothing } = Maybe
Last(Just([ 1, 2, 3 ]))
//=> Last( Just [ 1, 2, 3 ] )
Last(Nothing())
//=> Last( Nothing )
Last(null)
//=> Last( Just null )
Last(false)
//=> Last( Just false )
Last.empty :: () -> Last a
empty
provides the identity for the Monoid
in that when the value it provides is concat
ed to any other value, it will return the other value. In the case of Last
the result of empty
is Nothing
. empty
is available on both the Constructor and the Instance for convenience.
import Last from 'crocks/Last'
const { empty } = Last
empty()
//=> Last( Nothing )
Last(3)
.concat(empty())
//=> Last( Just 3 )
empty()
.concat(Last(3))
//=> Last( Just 3 )
Last a ~> b -> Boolean
Used to compare the underlying values of two Last
instances for equality by value, equals
takes any given argument and returns true
if the passed argument is a Last
with an underlying value equal to the underlying value of the Last
the method is being called on. If the passed argument is not a Last
or the underlying values are not equal, equals
will return false
.
import Last from 'crocks/Last'
import Maybe from 'crocks/Maybe'
Last(33)
.equals(Last(33))
//=> true
Last(42)
.equals(Last(10))
//=> false
Last({ a: 5 })
.equals({ a: 5 })
//=> false
Last(95)
.equals(95)
//=> false
Last(95)
.equals(Maybe.of(95))
//=> false
Last a ~> Last a -> Last a
concat
is used to combine two Semigroup
s of the same type under an operation specified by the Semigroup
. In the case of Last
, it will always provide the last non-empty value. All previous non-empty values will be thrown away and will always result in the last non-empty value.
import Last from 'crocks/Last'
import concat from 'crocks/pointfree/concat'
const a = Last('a')
const b = Last('b')
const c = Last('c')
a.concat(b)
//=> Last( Just "b" )
b.concat(a)
//=> Last( Just "a" )
concat(c, concat(b, a))
//=> Last( Just "c" )
concat(concat(c, b), a)
//=> Last( Just "c" )
concat(concat(a, b), c)
//=> Last( Just "a" )
Last a ~> a -> a
Last
wraps an underlying Maybe
which provides the ability to option out a value in the case of an empty
instance. Just like option
on a Maybe
instance, it takes a value as its argument. When run on an empty
instance, the provided default will be returned. If option
is run on a non-empty instance however, the wrapped value will be extracted not only from the Last
but also from the underlying Just
.
If the underlying Maybe
is desired, the valueOf
method can be used and will return the Maybe
instead.
import Last from 'crocks/Last'
import compose from 'crocks/helpers/compose'
import chain from 'crocks/pointfree/chain'
import getProp from 'crocks/Maybe/getProp'
import isString from 'crocks/predicates/isString'
import mconcatMap from 'crocks/helpers/mconcatMap'
import safe from 'crocks/Maybe/safe'
// stringVal :: a -> Maybe String
const stringVal = compose(
chain(safe(isString)),
getProp('val')
)
// lastValid :: [ a ] -> Last String
const lastValid =
mconcatMap(Last, stringVal)
// good :: [ Object ]
const good =
[ { val: 23 }, { val: 'string' }, { val: '23' } ]
// bad :: [ Object ]
const bad =
[ { val: 23 }, { val: null }, {} ]
lastValid(good)
.option('')
//=> "23"
lastValid(bad)
.option('')
//=> ""
Last a ~> () -> Maybe a
valueOf
is used on all crocks
Monoid
s as a means of extraction. While the extraction is available, types that implement valueOf
are not necessarily a Comonad
. This function is used primarily for convenience for some of the helper functions that ship with crocks
. Calling valueOf
on a Last
instance will result in the underlying Maybe
.
import Last from 'crocks/Last'
import Maybe from 'crocks/Maybe'
import valueOf from 'crocks/pointfree/valueOf'
const { Nothing } = Maybe
valueOf(Last(56))
//=> Just 56
valueOf(Last.empty())
//=> Nothing
Last(37)
.concat(Last(99))
.valueOf()
//=> Just 99
Last(Nothing())
.concat(Last.empty())
.valueOf()
//=> Nothing
crocks/Last/eitherToLast
eitherToLast :: Either b a -> Last a
eitherToLast :: (a -> Either c b) -> a -> Last b
Used to transform a given Either
instance to a Last
instance, eitherToLast
will turn a Right
instance into a non-empty Last
, wrapping the original value contained in the Right
. All Left
instances will map to an empty
Last
, mapping the originally contained value to a Unit
. Values on the Left
will be lost and as such this transformation is considered lossy in that regard.
Like all crocks
transformation functions, eitherToLast
has two possible signatures and will behave differently when passed either an Either
instance or a function that returns an instance of Either
. When passed the instance, a transformed Last
is returned. When passed an Either
returning function, a function will be returned that takes a given value and returns a Last
.
import Last from 'crocks/Last'
import Either from 'crocks/Either'
import eitherToLast from 'crocks/Last/eitherToLast'
import concat from 'crocks/pointfree/concat'
import constant from 'crocks/combinators/constant'
import flip from 'crocks/combinators/flip'
import ifElse from 'crocks/logic/ifElse'
import isNumber from 'crocks/predicates/isNumber'
import mapReduce from 'crocks/helpers/mapReduce'
const { Left, Right } = Either
// someNumber :: a -> Either String Number
const someNumber = ifElse(
isNumber,
Right,
constant(Left('Nope'))
)
// lastNumber :: [ a ] -> Last Number
const lastNumber = mapReduce(
eitherToLast(someNumber),
flip(concat),
Last.empty()
)
// "Bad Times" is lost, mapped to Nothing
eitherToLast(Left('Bad Times'))
//=> Last( Nothing )
eitherToLast(Right('correct'))
//=> Last( Just "correct" )
lastNumber([ 'string', null, 34, 76 ])
//=> Last( Just 76 )
lastNumber([ 'string', null, true ])
//=> Last( Nothing )
crocks/Last/firstToLast
firstToLast :: First a -> Last a
firstToLast :: (a -> First b) -> a -> Last b
Used to transform a given First
instance to a Last
instance, firstToLast
will turn a non-empty instance into a non-empty Last
wrapping the original value contained within the First
. All empty
instances will map to an empty
Last
.
Like all crocks
transformation functions, firstToLast
has two possible signatures and will behave differently when passed either a First
instance or a function that returns an instance of First
. When passed the instance, a transformed Last
is returned. When passed a First
returning function, a function will be returned that takes a given value and returns a Last
.
import Last from 'crocks/Last'
import First from 'crocks/First'
import firstToLast from 'crocks/Last/firstToLast'
import isString from 'crocks/predicates/isString'
import mconcatMap from 'crocks/helpers/mconcatMap'
import safe from 'crocks/Maybe/safe'
// firstString :: [ a ] -> First String
const firstString =
mconcatMap(First, safe(isString))
// unfixFirstString :: [ a ] -> Last String
const unfixFirstString =
firstToLast(firstString)
firstToLast(First.empty())
//=> Last( Nothing )
firstToLast(First(false))
//=> Last( Just false )
unfixFirstString([ 'one', 2, 'Three', 4 ])
//=> Last( Just "one" )
unfixFirstString([ 'one', 2, 'Three', 4 ])
.concat(Last('another string'))
//=> Last( Just "another string" )
unfixFirstString([ 1, 2, 3, 4 ])
.concat(Last('Last String'))
//=> Last( Just "Last String" )
crocks/Last/maybeToLast
maybeToLast :: Maybe a -> Last a
maybeToLast :: (a -> Maybe b) -> a -> Last b
Used to transform a given Maybe
instance to a Last
instance, maybeToLast
will turn a Just
into a non-empty Last
instance, wrapping the original value contained within the Last
. All Nothing
instances will map to an empty
Last
instance.
This function is available mostly for completion sake, as Last
can always take a Maybe
as its argument during construction. So while there is not a real need for this to be used for transforming instances, it can come in handy for lifting Maybe
returning functions.
Like all crocks
transformation functions, maybeToLast
has two possible signatures and will behave differently when passed either a Maybe
instance or a function that returns an instance of Maybe
. When passed the instance, a transformed Last
is returned. When passed a Maybe
returning function, a function will be returned that takes a given value and returns a Last
.
import Last from 'crocks/Last'
import Maybe from 'crocks/Maybe'
import maybeToLast from 'crocks/Last/maybeToLast'
import chain from 'crocks/pointfree/chain'
import compose from 'crocks/helpers/compose'
import getProp from 'crocks/Maybe/getProp'
import isNumber from 'crocks/predicates/isNumber'
import safe from 'crocks/Maybe/safe'
const { Nothing, Just } = Maybe
// numVal :: a -> Maybe Number
const numVal = compose(
chain(safe(isNumber)),
getProp('val')
)
// lastNumVal :: a -> Last Number
const lastNumVal =
maybeToLast(numVal)
maybeToLast(Just(99))
//=> Last( Just 99 )
maybeToLast(Nothing())
//=> Last( Nothing )
Last(Just(99))
//=> Last( Just 99 )
Last(Nothing())
//=> Last( Nothing )
Last(Just(80))
.concat(lastNumVal({ val: 97 }))
//=> Last( Just 97 )
lastNumVal({ val: 97 })
.concat(Last(80))
//=> Last( Just 80 )
lastNumVal(null)
.concat(Last(80))
//=> Last( Just 80 )
crocks/Last/resultToLast
resultToLast :: Result e a -> Last a
resultToLast :: (a -> Result e b) -> a -> Last b
Used to transform a given Result
instance to a Last
instance,resultToLast
will turn an Ok
instance into a non-empty Last
, wrapping the original value contained in the Ok
. All Err
instances will map to an empty
Last
, mapping the originally contained value to a Unit
. Values on the Err
will be lost and as such this transformation is considered lossy in that regard.
Like all crocks
transformation functions, resultToLast
has two possible signatures and will behave differently when passed either an Result
instance or a function that returns an instance of Result
. When passed the instance, a transformed Last
is returned. When passed a Result
returning function, a function will be returned that takes a given value and returns a Last
.
import Last from 'crocks/Last'
import Result from 'crocks/Result'
import resultToLast from 'crocks/Last/resultToLast'
import isNumber from 'crocks/predicates/isNumber'
import tryCatch from 'crocks/Result/tryCatch'
const { Err, Ok } = Result
function onlyNums(x) {
if(!isNumber(x)) {
throw new Error('something amiss')
}
return x
}
// lastNum :: a -> Last Number
const lastNum =
resultToLast(tryCatch(onlyNums))
// "this is bad" is lost, mapped to Nothing
resultToLast(Err('this is bad'))
//=> Last( Nothing )
resultToLast(Ok('this is great'))
//=> Last( Just "this is great" )
lastNum(90)
.concat(Last(0))
//=> Last( Just 0 )
lastNum(null)
.concat(Last(0))
//=> Last( Just 0 )
Contribute on Github! Edit this section.