Kleene logic in Scala
/* Copyright 2017 David Szakallas, MIT License */ | |
/* | |
Kleene logic represented on 2 bits, implemented as a value class. | |
00: false | |
{01,10}: null | |
11: true | |
*/ | |
class Kleene(val value: Int) extends AnyVal { | |
def &&(rhs: Kleene): Kleene = new Kleene(value & rhs.value) | |
def ||(rhs: Kleene): Kleene = new Kleene(value | rhs.value) | |
def unary_! : Kleene = new Kleene(value ^ 0x3) | |
def ==(rhs: Kleene): Kleene = !(this != rhs) | |
def !=(rhs: Kleene): Kleene = { | |
val first = value ^ rhs.value | |
val second = value ^ rhs.flippedValue | |
// MSbs are ANDed, LSbs are ORed | |
new Kleene((first & second & 0x2) | ((first | second) & 0x1)) | |
} | |
def isFalse: Boolean = value == 0x0 | |
def isTrue: Boolean = value == 0x3 | |
def isNull: Boolean = value == 0x1 || value == 0x2 | |
private def flippedValue: Int = (value & 0x1) << 1 | (value & 0x2) >> 1 | |
implicit def toOption: Option[Boolean] = { | |
if (this.isTrue) { | |
Some(true) | |
} else if (this.isFalse) { | |
Some(false) | |
} else { | |
None | |
} | |
} | |
} | |
object Kleene { | |
def False: Kleene = new Kleene(0) | |
def Null: Kleene = new Kleene(1) | |
def True: Kleene = new Kleene(3) | |
implicit def fromBoolean(b: Boolean): Kleene = if (b) True else False | |
implicit def fromOption[B <: Boolean](o: Option[B]): Kleene = o match { | |
case Some(b) => fromBoolean(b) | |
case _ => Null | |
} | |
implicit class OptionBooleanToKleene[B <: Boolean](val opt: Option[B]) extends AnyVal { | |
def toKleene: Kleene = fromOption(opt) | |
} | |
} |
/* Copyright 2017 David Szakallas, MIT License */ | |
import simulacrum.{op, typeclass} | |
@typeclass trait GenKleeneLike[-A] { | |
@op("|=|") def eq(x: A, y: A): Option[Boolean] | |
@op("|!|") def ne(x: A, y: A): Option[Boolean] | |
} | |
object GenKleeneLike { | |
class GenKleeneLikeForOption[Opt <: Option[Any]] extends GenKleeneLike[Opt] { | |
override def eq(x: Opt, y: Opt): Option[Boolean] = | |
for { _x <- x; _y <- y } yield _x == _y | |
override def ne(x: Opt, y: Opt): Option[Boolean] = | |
for { _x <- x; _y <- y } yield _x != _y | |
} | |
implicit def genKleeneLikeForOption[Opt <: Option[Any]]: GenKleeneLike[Opt] = new GenKleeneLikeForOption[Opt] | |
} | |
@typeclass trait KleeneLike[-A] extends GenKleeneLike[A] { | |
@op("&&") def and(x: A, y: A): Option[Boolean] | |
@op("||") def or(x: A, y: A): Option[Boolean] | |
@op("unary_!") def not(x: A): Option[Boolean] | |
} | |
object KleeneLike { | |
import GenKleeneLike.GenKleeneLikeForOption | |
class KleeneLikeForOptionBoolean[Opt <: Option[Boolean]] extends GenKleeneLikeForOption[Opt] with KleeneLike[Opt] { | |
override def and(x: Opt, y: Opt): Option[Boolean] = (x, y) match { | |
case (Some(true), Some(true)) => Some(true) | |
case (Some(false), _) => Some(false) | |
case (_, Some(false)) => Some(false) | |
case _ => None | |
} | |
override def or(x: Opt, y: Opt): Option[Boolean] = (x, y) match { | |
case (Some(false), Some(false)) => Some(false) | |
case (Some(true), _) => Some(true) | |
case (_, Some(true)) => Some(true) | |
case _ => None | |
} | |
override def not(x: Opt): Option[Boolean] = | |
for { _x <- x } yield !_x | |
} | |
implicit def optionBooleanKleeneLike[OptB <: Option[Boolean]]: KleeneLike[OptB] = new KleeneLikeForOptionBoolean[OptB] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment