Skip to content

Instantly share code, notes, and snippets.

@otobrglez
Created September 29, 2021 10:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save otobrglez/449acd20db22771963cbc51c9e0f1c38 to your computer and use it in GitHub Desktop.
Save otobrglez/449acd20db22771963cbc51c9e0f1c38 to your computer and use it in GitHub Desktop.
Experimenting with Monoids and Validated
package com.pollpass.experimental
import cats.data.ValidatedNec
object Example1 {
def run(): Unit = {
type Checker = Char => Boolean
val isBraille: Checker = _ => false
val isEmoji: Checker = _ => false
val isForbidden: Char => Boolean = char =>
List(
isEmoji,
isBraille,
(_.isUpper): Checker).foldLeft(false)((agg, checker) => agg || checker(char))
println(s"Is forbidden => ${isForbidden("😆".charAt(0))}")
}
}
object Example2 {
def run(): Unit = {
import cats._
import cats.implicits._
import cats.syntax._
type Checker = Char => Boolean
val isBraille: Checker = _ => false
val isEmoji: Checker = _ => false
implicit val checkerMonoid: Monoid[Checker] = new Monoid[Checker] {
val empty: Checker = _ => false
def combine(x: Checker, y: Checker): Checker = char => x(char) || y(char)
}
def combineCheckers[A: Monoid](checkers: A*): A =
checkers.foldLeft(Monoid[A].empty)(Monoid.combine)
val isForbidden1: Checker = combineCheckers(isBraille, isEmoji)
val isForbidden2: Checker = isBraille |+| isEmoji
val isForbidden3: Checker = isBraille |+| isEmoji |+| (_.isUpper)
val isForbidden4: Checker = List(isBraille, isEmoji, (_.isUpper): Checker)
.foldLeft(Monoid[Checker].empty)(Monoid[Checker].combine)
println(
s"""Is forbidden (with Cats)
| => ${isForbidden1("😆".charAt(0))}
| => ${isForbidden2('X')}
| => ${isForbidden3('X')}
| => ${isForbidden4('X')}
|""".stripMargin)
}
}
object Example3 {
def run() = {
import cats.implicits._
import cats.data.Validated._
sealed trait ValidationError extends Exception
final case class ContainsBraille(message: String) extends ValidationError
final case class ContainsEmoji(message: String) extends ValidationError
type Checker[E <: ValidationError, T] = Char => ValidatedNec[E, T]
def isBraille: Checker[ContainsBraille, Boolean] = char =>
if (char != ':') true.validNec else ContainsBraille("Found braille characters.").invalidNec
def isEmoji: Checker[ContainsEmoji, Boolean] = char =>
Either.cond(char == "😆".charAt(0), true, ContainsEmoji(s"Found emoji in ${char}")).toValidatedNec
def isForbidden(char: Char): ValidatedNec[ValidationError, Boolean] =
(isBraille(char), isEmoji(char)).mapN { case (true, true) => true }
println(
s"""
|1 => ${isForbidden('X')}
|""".stripMargin)
}
}
object Main extends App {
Example1.run()
Example2.run()
Example3.run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment