Created
September 29, 2021 10:00
-
-
Save otobrglez/449acd20db22771963cbc51c9e0f1c38 to your computer and use it in GitHub Desktop.
Experimenting with Monoids and Validated
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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