Some typeclasses inspired and powered by shapeless
Will allow to find a type A in an HList L, if the type is not present it returns None, otherwise Some[A]
Similar to Find, but for a group of elements, if all the elements of the S are present in L it returns Some[S] otherwise None
Converts a List[L] to an Option[HList]. The ListToHList implicit class exposes two features.
.toProduct[A]: convert List[L] to an Option[A].
.findByType[B]: find type B within List[L]
import ListToHList.Ops
sealed trait A
case class B() extends A
case class C() extends A
case class D(b: B, c: C)
val listA: List[A] = List(B(), C())
listA.toProduct[D] === Some(D(B(), C()))
listA.findByType[B] === Some(B())For Coproducts L and S, Convert takes a value of type L and converts it to type S.
type A = String :+: Double :+: CNil
type B = Double :+: String :+: List[Int] :+: CNil
Coproduct[A]("test").convert[B] === Some(Coproduct[B]("test"))
For a Seq of Coproducts C, convert to HList of type L
type A = Int :+: String :+: CNil
type L = String :: Int :: HNil
Seq(Coproduct[A](1), Coproduct[A]("a")).toHList[L] === Some("a" :: 1 :: HNil))
case class Foo(i:Int, s:String)
Seq(Coproduct[A](1), Coproduct[A]("a")).toHList[Foo] === Some(Food("a", 1))
Takes an HList of functions FF and an HList of potential arguments Context. It applies the arguments to the functions for which all the arguments are present. It returns an HList with the results. It will not compile if there is a function that cannot be applied.
val functions =
{ (x: String, i: Int, d: Double) => d.toInt * i } ::
{ (x: String, i: Int) => s"$x + $i" } ::
{ (x: String, s: Char, i: Int) => i.toDouble } ::
{ (x: String, s: Char, i: Int) => s.toInt + i * 2 + x.size } ::
{ (x: String) => x.size } ::
{ (x: Char) => x.toInt } ::
HNil
SelectFunctions.applyAll(1, hi)(functions) // won't compile
SelectFunctions.applyAll(hi, 'a', 1)(functions) == "hi + 1" :: 1.0 :: 101 :: 2 :: 97 :: HNilTakes an HList of HLists of functions and an HList of potential arguments, and uses SelectFunctions[Context, FF] to calculate the resulting HList.
val functions1 =
{ (x: String, i: Int) => (x.size + i) } ::
{ (x: String, s: Char, i: Int) => (s.toInt + i * 2 + x.size) } ::
HNil
val functions2 =
{ (x: String, s: Char, i: Int) => (s.toInt + i + x.size) } ::
{ (i: Int) => i.toDouble } ::
HNil
val functions = functions1 ::
functions2 ::
HNil
FlattenFunctions.applyAll(1, "a", 'a')(functions) === 2 :: 1.0 :: 99 :: HNilIt compares two cases classes excluding specific field names rather than types.
import typeless.hlist.EqualsIgnoringFields.Ops
sealed trait Monarch
case class Butterflies(
_id: Long,
date: Long,
count: Int
) extends Monarch
case class Dictator(
_id: Long,
date: Long,
count: Int
) extends Monarch
val butterfliesStation1 = Butterflies(
_id = 1,
date = 1131,
count = 3
)
val butterfliesStation2 = Butterflies(
_id = 2,
date = 1131,
count = 2
)
// the two objects are the same if we ignore those two fields
assert(butterfliesStation1.equalsIgnoringFields(field => field == '_id || field == 'count)(butterfliesStation2))
// the two objects are different if not ignoring `count`
assert(!butterfliesStation1.equalsIgnoringFields(_ == '_id)(butterfliesStation2))
// the two objects are different, period
assert(butterfliesStation1 != butterfliesStation2)
libraryDependencies += "ai.x" %% "typeless" % "0.6.0"