Fyne Thyngges provided by Learning Objects, for Use with ScalaZ and Libraries of a similar Nature and Quality.
Convenient syntax for converting to and among monads.
Syntaces, including the flappy birds, to operate within \/
disjunctions.
for {
_ <- 0.right[Err] // ScalaZ
_ <- Option(1) \/> Err.IsNone // ScalaZ
_ <- true \/> Err.IsFalse
_ <- false \/>! Err.IsTrue
_ <- Try(2) \/> Err.forThrowable
_ <- Try(3) \/>| Err.IsFailure
_ <- \@~*/(op) -\/> Err.forThrowable
} yield ???
Syntaces to operate within the Try
monad.
for {
_ <- 0.success
_ <- Ex("Bah").failure
_ <- Option(1) <@~* Ex("None")
_ <- true <@~* Ex("false")
_ <- false *~@> Ex("true")
_ <- true <@~* Ex("false") *> 3 // add a starry bird
_ <- 2.right[Ex].toTry
_ <- this.asInstanceOf_![That]
_ <- true either 3 orFailure Ex("false")
_ <- Option(Try(4)) flatToTry Ex("None")
_ <- Option(5) thenFailure (Ex("None"), 6)
_ <- Option("Some") thenHollowFailure Ex.apply
_ <- Option("Some") elseHollowVictory Ex.apply
_ <- Option(Ex("Some")) toFailure 8
} yield ???
Syntaces to operate within the Task
monad.
for {
i <- 0.now
j <- Try(0).toTask
k <- Option(0) *#@% Ex("None")
} yield ???
Syntaces to operate within the Validation
monad.
for {
_ <- 0.success[Err] // ScalaZ
_ <- Option(1) elseInvalid Err.IsNone
_ <- Option("bah") thenInvalid Err.forString
_ <- Option("bah") thenInvalid 2
_ <- true elseFailure (Err.IsFalse, 3)
_ <- false thenFailure (Error.IsTrue, 4)
} yield ???
Similarly for ValidationNel
.
The Hypermonad
typeclass describes a monad that supports mapping flatter
than flat. For example, given a list of ids and a
function from an id to perhaps a list of entities, it can flatter map to
a single list of all the associated entities.
val entityMap: Map[Long, List[Entity]] = ???
val ids: List[Long] = ???
val entities: List[Entity] = ids.flatterMap(entityMap.get)
Hypermonads can also flatten flatter.
val list3: List[List[List[Int]]] = ???
val ints: List[Int] = list3.hyperFlatten
A strict tree, much as StrictTree
, but based on List
and thus avoidant
of the moral perils of Vector
.
val tree = 0.listNode(1.listLeaf, 2.listLeaf)
tree.flatten must_=== List(0, 1, 2)
Evidence for a type that has a zero but is not necessarily semigroupal.
trait Zero[A] {
def zero: A
def isZero(a: A): Boolean
}
All Monoid
s with Equal
, IsEmpty
s and Numeric
s have a Zero
.
A minimal syntax is provided. Other zeroic syntaces are provided in different contexts.
Nil.isZero must_=== true
1.nonZero must_=== true
OptionNZ
wraps a value in an Option
, filtering out any zeroes.
Use this, for example, to filter out empty strings.
OptionNZ("") must_=== None
OptionNZ("Bob") must_=== Some("Bob")
Related, OptionNB
wraps a String
in an Option
, filtering out any
blanks.
OptionNB(" ") must_=== None
OptionNZ("Old Brunswick") must_=== Some("Old Brunswick")
The foldSC
operation, aka ??>
, short-circuits a function to the resulting
zero if the parameter to the function is an empty collection. Use this, for
example, to avoid performing unnecessary I/O operations or calling database
libraries that fail on empty lists.
val ids: List[Long] = ???
val loadUsers: List[Long] => List[User] = ???
val users: List[User] = ids ??> loadUsers
Used to efficiently track recent data.
Tracks which data have been recently added, for the purposes of deduplication.
val dedup = BucketGenerationalDedup.empty[Symbol](3.minutes, 3)
dedup += 'a
dedup contains 'a must_=== true
sleep(4.minutes)
dedup contains 'a must_=== false
Tracks how many of each datum have been recently added to the bag.
val bag = BucketGenerationalBag.empty[Symbol](3.minutes, 3)
bag += 'a
bag count 'a must_=== 1
sleep(1.minutes)
bag += 'a
bag count 'a must_=== 2
sleep(4.minutes)
bag count 'a must_=== 0
A queue of key-value pairs that releases values fairly across the keyspace.
val queue = UnboundedBlockingFairKeyedQueue.empty[Symbol, Int]
queue.offer('a -> 1)
queue.offer('a -> 2)
queue.offer('b -> 3)
queue.take() must_=== 1
queue.take() must_=== 3
queue.take() must_=== 2
Tracks the delta between two sets.
val set0: Set[Int] = ???
val set1: Set[Int] = ???
val delta = SetDelta from set0 to set1
set0 |: delta must_=== set1
With added support for util.Optional
. Including, but not limited
to:
Option(a) <|? println // tap on the contents
Option(a) -<| sys.exit() // tap on absence
Option(a) flatOpt fa // flat map to nullable
Option(a) orZ // get or zero
Option(a) foldZ fa // map or zero
Option(a) filterNZ // filter non-zero
Option(a) mapNZ fa // map then filter non-zero
Option(a0) - a1 // filter out
Option(a).isTrue // container of truth
Option(a0) =&= Option(a1) // both present and equal
Option(a0) max a1 // maximality
Option(a0) max Option(a1) // co-maximality
Option(a0) min a1 // minimality
Option(a0) min Option(a1) // co-minimality
Option(a) when b // filter by boolean
Option(a) unless b // filter by invert boolean
Option(a).accept[Dog] // filter by type
Option(a) \&/ Option(b) // to these
With added support for lang.Boolean
. Including, but not limited to:
bool noption a // some if false, else none
bool flatOption optA // none if false, or else optA
bool flatNoption optA // none if true, or else optA
false ??? Some(1) must_=== 0 // zero if false or absent, else a
true <|? println("true") // tap on true
false <|! println("false") // tap on false
bool either a orElse optA // flat either or
The \|/
bifunctor admits either the left, the right, both or neither.
Contrast with \&/
which refuses to admit neither and \/
which
admits neither neither nor both.
val optA: Option[A] = ???
val optB: Option[B] = ???
val ab = optA \|/ optB
val cd = enb bimap (fac, fbd)
Consider the blessed font.