Skip to content

Instantly share code, notes, and snippets.

@dszakallas
Last active June 20, 2017 11:28
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 dszakallas/c595fe23b5a1a960f997024cb63a3fff to your computer and use it in GitHub Desktop.
Save dszakallas/c595fe23b5a1a960f997024cb63a3fff to your computer and use it in GitHub Desktop.
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