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 :: HNil
Takes 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 :: HNil
It 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"