Last active
February 20, 2023 10:02
-
-
Save fancellu/9a1aafd70b5c316b14f9 to your computer and use it in GitHub Desktop.
Examples with Shapeless 2.0, easier to understand from examples. Taken from docs, more examples/comments added etc
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
// Coproduct is extension of Either concept, to N multually exlusive choices | |
type ISB = Int :+: String :+: Boolean :+: CNil | |
val isb = Coproduct[ISB]("foo") //> isb : qaaz.ISB = foo | |
isb.select[Int] //> res0: Option[Int] = None | |
isb.select[String] //> res1: Option[String] = Some(foo) | |
object size extends Poly1 { | |
implicit def caseInt = at[Int](i => (i, i)) | |
implicit def caseString = at[String](s => (s, s.length)) | |
implicit def caseBoolean = at[Boolean](b => (b, 1)) | |
} | |
val res2=isb map size //> res2 : shapeless.:+:[(Int, Int),shapeless.:+:[(String, Int),shapeless.:+:[( | |
//| Boolean, Int),shapeless.CNil]]] = (foo,3) | |
res2.select[(String, Int)] //> res2: Option[(String, Int)] = Some((foo,3)) | |
import record.RecordType, syntax.singleton._, union._ | |
// make a schema LIKE this, i.e. an examplar | |
val uSchema = RecordType.like('i ->> 23 :: 's ->> "foo" :: 'b ->> true :: HNil) | |
type U = uSchema.Union | |
val u = Coproduct[U]('s ->> "woof") // Inject a String into the union at label 's | |
//u: U = foo | |
u.get('i) // Nothing at 'i | |
//res0: Option[Int] = None | |
u.get('s) // Something at 's | |
//res1: Option[String] = Some(woof) | |
u.get('b) // Nothing at 'b | |
//res2: Option[Boolean] = None | |
// Would not compile | |
// println(u.get('x)) | |
{ | |
val uSchema2 = RecordType.like('i ->> 23 :: 'i2 ->> 100 :: HNil) | |
type U = uSchema2.Union | |
val u = Coproduct[U]('i2 ->> 1000) | |
println(u.get('i)) | |
//None | |
println(u.get('i2)) | |
//Some(1000) | |
} |
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
/** | |
* Generic[T], where T is a case class or an abstract type at the root of a case class hierarchy, | |
* maps between values of T and a generic sum of products representation (HLists and Coproducts) | |
**/ | |
case class Foo(i: Int, s: String, b: Boolean) | |
val fooGen = Generic[Foo] //> fooGen : shapeless.Generic[qaaz.Foo]{type Repr = shapeless.::[Int,shapeless | |
//| .::[String,shapeless.::[Boolean,shapeless.HNil]]]} = qaaz$$anonfun$main$1$fr | |
//| esh$macro$45$1@2b05039f | |
val foo = Foo(23, "foo", true) //> foo : qaaz.Foo = Foo(23,foo,true) | |
val hlist=fooGen.to(foo) //> hlist : qaaz.fooGen.Repr = 23 :: foo :: true :: HNil | |
val hlist2=13 :: hlist.tail //> hlist2 : shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeles | |
//| s.HNil]]] = 13 :: foo :: true :: HNil | |
fooGen.from(hlist2) //> res0: qaaz.Foo = Foo(13,foo,true) | |
// Simple recursive case class family | |
sealed trait Tree[T] | |
case class Leaf[T](t: T) extends Tree[T] | |
case class Node[T](left: Tree[T], right: Tree[T]) extends Tree[T] | |
import poly._ | |
// Polymorphic function which adds 1 to any Int and is the identity | |
// on all other values | |
object inc extends ->((i: Int) => i+1) | |
val tree: Tree[Int] = | |
Node( | |
Node( | |
Node( | |
Leaf(1), | |
Node( | |
Leaf(2), | |
Leaf(3) | |
) | |
), | |
Leaf(4) | |
), | |
Node( | |
Leaf(5), | |
Leaf(6) | |
) | |
) //> tree : qaaz.Tree[Int] = Node(Node(Node(Leaf(1),Node(Leaf(2),Leaf(3))),Leaf( | |
//| 4)),Node(Leaf(5),Leaf(6))) | |
// Transform tree by applying inc everywhere | |
val out=everywhere(inc)(tree) //> out : qaaz.Tree[Int] = Node(Node(Node(Leaf(2),Node(Leaf(3),Leaf(4))),Leaf(5 | |
//| )),Node(Leaf(6),Leaf(7))) | |
// LabelledGeneric | |
import record._, syntax.singleton._ | |
case class Book(author: String, title: String, id: Int, price: Double) | |
val bookGen = LabelledGeneric[Book] | |
val tapl = Book("Benjamin Pierce", "Types and Programming Languages", 262162091, 44.11) | |
val rec = bookGen.to(tapl) // Convert case class value to generic representation | |
//rec: bookGen.Repr = Benjamin Pierce :: Types and Programming Languages :: 262162091 :: 44.11 :: HNil | |
rec('price) // Access the price field symbolically, maintaining type information | |
//res0: Double = 44.11 | |
bookGen.from(rec.updateWith('price)(_+2.0)) // type safe operations on fields | |
//res1: Book = Book(Benjamin Pierce,Types and Programming Languages,262162091,46.11) | |
case class ExtendedBook(author: String, title: String, id: Int, price: Double, inPrint: Boolean) | |
val bookExtGen = LabelledGeneric[ExtendedBook] | |
val extendedCase=bookExtGen.from(rec + ('inPrint ->> true)) // map values between case classes via generic representation | |
//extendedCase: ExtendedBook = ExtendedBook(Benjamin Pierce,Types and Programming Languages,262162091,44.11,true) | |
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
import shapeless._ | |
import poly._ | |
import syntax.zipper._ | |
object choose extends (Set ~> Option) { | |
def apply[T](s : Set[T]) = s.headOption | |
} | |
val sets = Set(1) :: Set("foo") :: HNil //> sets : shapeless.::[scala.collection.immutable.Set[Int],shapeless.::[scala. | |
//| collection.immutable.Set[String],shapeless.HNil]] = Set(1) :: Set(foo) :: HN | |
//| il | |
val opts = sets map choose // map selects cases of choose for each HList element | |
//> opts : shapeless.::[Option[Int],shapeless.::[Option[String],shapeless.HNil] | |
//| ] = Some(1) :: Some(foo) :: HNil | |
val l = (23 :: "foo" :: HNil) :: HNil :: (true :: HNil) :: HNil | |
//> l : shapeless.::[shapeless.::[Int,shapeless.::[String,shapeless.HNil]],shap | |
//| eless.::[shapeless.HNil.type,shapeless.::[shapeless.::[Boolean,shapeless.HNi | |
//| l],shapeless.HNil]]] = 23 :: foo :: HNil :: HNil :: true :: HNil :: HNil | |
(l flatMap identity) //> res0: shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeless.HN | |
//| il]]] = 23 :: foo :: true :: HNil | |
object size extends Poly1 { | |
implicit def caseInt = at[Int](x => 1) | |
implicit def caseString = at[String](_.length) | |
implicit def caseTuple[T, U] | |
(implicit st : Case.Aux[T, Int], su : Case.Aux[U, Int]) = | |
at[(T, U)](t => size(t._1)+size(t._2)) | |
} | |
object addSize extends Poly2 { | |
implicit def default[T](implicit st: size.Case.Aux[T, Int]) = | |
at[Int, T]{ (acc, t) => acc+size(t) } | |
} | |
val l2 = 23 :: "foo" :: (13, "wibble") :: HNil //> l2 : shapeless.::[Int,shapeless.::[String,shapeless.::[(Int, String),shapel | |
//| ess.HNil]]] = 23 :: foo :: (13,wibble) :: HNil | |
println(l2.foldLeft(0)(addSize)) //> 11 | |
// 11 | |
val l3 = 1 :: "foo" :: 3.0 :: HNil //> l3 : shapeless.::[Int,shapeless.::[String,shapeless.::[Double,shapeless.HNi | |
//| l]]] = 1 :: foo :: 3.0 :: HNil | |
val zipper=l3.toZipper //> zipper : shapeless.Zipper[shapeless.::[Int,shapeless.::[String,shapeless.:: | |
//| [Double,shapeless.HNil]]],shapeless.HNil,this.Repr,None.type] = Zipper(HNil, | |
//| 1 :: foo :: 3.0 :: HNil,None) | |
// a zipper is like a functional cursor. reify call makes it real, i.e. no longer a zipper | |
zipper.insert("A").right.insert("B").right.insert("C").right.insert("D").reify | |
//> res1: shapeless.::[String,shapeless.::[Int,shapeless.::[String,shapeless.:: | |
//| [String,shapeless.::[String,shapeless.::[Double,shapeless.::[String,shapele | |
//| ss.HNil]]]]]]] = A :: 1 :: B :: foo :: C :: 3.0 :: D :: HNil | |
zipper.right.put(("wibble", 45)).reify //> 1 :: (wibble,45) :: 3.0 :: HNil | |
// right moves cursor to foo, put overwrites | |
zipper.right.delete.reify //> 1 :: 3.0 :: HNil | |
zipper.last.left.insert("bar").reify //> 1 :: foo :: bar :: 3.0 :: HNil | |
// index into HList | |
val l9 = 23 :: "foo" :: true :: HNil //> l : shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeless.HNi | |
//| l]]] = 23 :: foo :: true :: HNil | |
l9(1) //> res0: String = foo |
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
import shapeless._ | |
import poly._ | |
trait Fruit | |
case class Apple() extends Fruit | |
case class Pear() extends Fruit | |
type FFFF = Fruit :: Fruit :: Fruit :: Fruit :: HNil | |
type APAP = Apple :: Pear :: Apple :: Pear :: HNil | |
val a : Apple = Apple() //> a : yyy.Apple = Apple() | |
val p : Pear = Pear() //> p : yyy.Pear = Pear() | |
val apap : APAP = a :: p :: a :: p :: HNil //> apap : yyy.APAP = Apple() :: Pear() :: Apple() :: Pear() :: HNil | |
val ffff : FFFF = apap //> ffff : yyy.FFFF = Apple() :: Pear() :: Apple() :: Pear() :: HNil | |
// APAP <: FFFF i.e. covariant | |
// Will not compile because of apple where pear expected | |
// val badapple:APAP=a :: p :: a :: a ::HNil | |
apap.unify //> res0: shapeless.::[Product with Serializable with yyy.Fruit,shapeless.::[Pro | |
//| duct with Serializable with yyy.Fruit,shapeless.::[Product with Serializable | |
//| with yyy.Fruit,shapeless.::[Product with Serializable with yyy.Fruit,shapel | |
//| ess.HNil]]]] = Apple() :: Pear() :: Apple() :: Pear() :: HNil | |
// note unify emits HList with least upper bound, i.e. Fruit | |
apap.toList //> res1: List[Product with Serializable with yyy.Fruit] = List(Apple(), Pear(), | |
//| Apple(), Pear()) | |
import syntax.typeable._ | |
val precise = ffff.cast[APAP] //> precise : Option[yyy.APAP] = Some(Apple() :: Pear() :: Apple() :: Pear() :: | |
//| HNil) | |
val pppp=p :: p :: p :: p ::HNil //> pppp : shapeless.::[yyy.Pear,shapeless.::[yyy.Pear,shapeless.::[yyy.Pear,sh | |
//| apeless.::[yyy.Pear,shapeless.HNil]]]] = Pear() :: Pear() :: Pear() :: Pear( | |
//| ) :: HNil | |
val precise2 = pppp.cast[APAP] //> precise2 : Option[yyy.APAP] = None | |
// as you can see, this fails with a None. The wonders of Option |
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
//Heterogenous maps | |
// Key/value relation to be enforced: Strings map to Ints and vice versa | |
class BiMapIS[K, V] | |
implicit val intToString = new BiMapIS[Int, String] | |
//> intToString : qaaz.BiMapIS[Int,String] = qaaz$BiMapIS@66cd51c3 | |
implicit val stringToInt = new BiMapIS[String, Int] | |
//> stringToInt : qaaz.BiMapIS[String,Int] = qaaz$BiMapIS@2d6e8792 | |
val hm = HMap[BiMapIS](23 -> "foo", "bar" -> 13) //> hm : shapeless.HMap[qaaz.BiMapIS] = shapeless.HMap@13a57a3b | |
//val hm2 = HMap[BiMapIS](23 -> "foo", 23 -> 13) // Does not compile | |
hm.get(23) //> res0: Option[String] = Some(foo) | |
hm.get("bar") //> res1: Option[Int] = Some(13) | |
import hm._ | |
val l = 23 :: "bar" :: HNil //> l : shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 23 :: bar :: HN | |
//| il | |
l map hm //> res2: shapeless.::[String,shapeless.::[Int,shapeless.HNil]] = foo :: 13 :: H | |
//| Nil |
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
// A pair of ordinary case classes ... | |
case class Address(street : String, city : String, postcode : String) | |
case class Person(name : String, age : Int, address : Address) | |
// Some lenses over Person/Address ... | |
val nameLens = lens[Person] >> 'name | |
val ageLens = lens[Person] >> 'age | |
val addressLens = lens[Person] >> 'address | |
val streetLens = lens[Person] >> 'address >> 'street | |
val cityLens = lens[Person] >> 'address >> 'city | |
val postcodeLens = lens[Person] >> 'address >> 'postcode | |
val person = Person("Joe Grey", 37, Address("Southover Street", "Brighton", "BN2 9UA")) | |
//person: Person = Person(Joe Grey,37,Address(Southover Street,Brighton,BN2 9UA)) | |
val age1 = ageLens.get(person) // Read field, note inferred type | |
//age1: Int = 37 | |
val person2 = ageLens.set(person)(38) // Update field | |
//person2: Person = Person(Joe Grey,38,Address(Southover Street,Brighton,BN2 9UA)) | |
val person3 = ageLens.modify(person2)(_ + 1) // Transform field | |
//person3: Person = Person(Joe Grey,39,Address(Southover Street,Brighton,BN2 9UA)) | |
val street = streetLens.get(person3) // Read nested field | |
//street: String = Southover Street | |
val person4 = streetLens.set(person3)("Montpelier Road") // Update nested field | |
//person4: Person = Person(Joe Grey,39,Address(Montpelier Road,Brighton,BN2 9UA)) |
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
import shapeless._ | |
import poly._ | |
// choose is a function from Sets to Options with no type specific cases, i.e. polymorphic | |
object choose extends (Set ~> Option) { | |
def apply[T](s : Set[T]) = s.headOption | |
} | |
def choose2[T](s:Set[T])=s.headOption //> choose2: [T](s: Set[T])Option[T] | |
choose(Set(1, 2, 3)) //> res0: Option[Int] = Some(1) | |
choose(Set('a', 'b', 'c')) //> res1: Option[Char] = Some(a) | |
choose2(Set(1, 2, 3)) //> res2: Option[Int] = Some(1) | |
choose2(Set('a', 'b', 'c')) //> res3: Option[Char] = Some(a) | |
// So far looks the same | |
def pairApply(f: Set ~> Option) = (f(Set(1, 2, 3)), f(Set('a', 'b', 'c'))) | |
//> pairApply: (f: shapeless.poly.~>[Set,Option])(Option[Int], Option[Char]) | |
pairApply(choose) //> res4: (Option[Int], Option[Char]) = (Some(1),Some(a)) | |
// pairApply2 can't take T, will barf. because not polymorphic. T can't be Int and Char at same time | |
def pairApply2[_](f: Set[_] => Option[_]) = (f(Set(1, 2, 3)), f(Set('a', 'b', 'c'))) | |
//> pairApply2: [_](f: Set[_] => Option[_])(Option[Any], Option[Any]) | |
def choose3[_](s:Set[_])=s.headOption //> choose3: [_](s: Set[_])Option[Any] | |
// Can't use choose2 else | |
// Description Resource Path Location Type | |
// type mismatch; found : Set[T] => Option[T] required: Set[_] => Option[_] scala.sc /Scala2 line 33 Scala Problem | |
// polymorphic expression cannot be instantiated to expected type; found : [T]Set[T] => Option[T] required: Set[_] => Option[_] scala.sc /Scala2 line 33 Scala Problem | |
pairApply2(choose3) //> res5: (Option[Any], Option[Any]) = (Some(1),Some(a)) | |
// Note retuned as option[Any] |
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
import shapeless._ | |
import poly._ | |
// size is a function from Ints or Strings or pairs to a 'size' defined | |
// by type specific cases | |
object size extends Poly1 { | |
implicit def caseInt = at[Int](x => 1) | |
implicit def caseString = at[String](_.length) | |
implicit def caseTuple[T, U] | |
(implicit st : Case.Aux[T, Int], su : Case.Aux[U, Int]) = | |
at[(T, U)](t => size(t._1)+size(t._2)) | |
} | |
size(23) //> res0: Int = 1 | |
size("foo") //> res1: Int = 3 | |
size((23, "foo")) //> res2: Int = 4 | |
size(((23, "foo"), 13)) //> res3: Int = 5 | |
object incr extends Poly1 { | |
implicit def caseInt = at[Int](_+1) | |
implicit def caseString = at[String](s=>s+s.last) | |
implicit def caseTuple[T, U] | |
(implicit st : Case.Aux[T, T], su : Case.Aux[U, U]) = | |
at[(T, U)](t => (this(t._1),this(t._2))) | |
} | |
incr(23) //> res4: Int = 24 | |
incr("hello") //> res5: String = helloo | |
incr((33,44)) //> res6: (Int, Int) = (34,45) | |
incr(("cat",44)) //> res7: (String, Int) = (catt,45) |
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
import shapeless._ ; import syntax.singleton._ ; import record._ | |
val book = | |
("author" ->> "Benjamin Pierce") :: | |
("title" ->> "Types and Programming Languages") :: | |
("id" ->> 262162091) :: | |
("price" ->> 44.11) :: | |
HNil | |
book("author") // Note result type ... | |
// res0: String = Benjamin Pierce | |
book("title") // Note result type ... | |
//res1: String = Types and Programming Languages | |
book("id") // Note result type ... | |
//res2: Int = 262162091 | |
book("price") // Note result type ... | |
//res3: Double = 44.11 | |
book.keys // Keys are materialized from singleton types encoded in value type | |
//res4: String("author") :: String("title") :: String("id") :: String("price") :: HNil = | |
// author :: title :: id :: price :: HNil | |
book.values | |
//res5: String :: String :: Int :: Double :: HNil = | |
// Benjamin Pierce :: Types and Programming Languages :: 262162091 :: 44.11 :: HNil | |
val newPrice = book("price")+2.0 | |
//newPrice: Double = 46.11 | |
val updated = book +("price" ->> newPrice) // Update an existing field | |
//updated: ... complex type elided ... = | |
// Benjamin Pierce :: Types and Programming Languages :: 262162091 :: 46.11 :: HNil | |
updated("price") | |
//res6: Double = 46.11 | |
val extended = updated + ("inPrint" ->> true) // Add a new field | |
//extended: ... complex type elided ... = | |
// Benjamin Pierce :: Types and Programming Languages :: 262162091 :: 46.11 :: true :: HNil | |
val noId = extended - "id" // Removed a field | |
//noId: ... complex type elided ... = | |
// Benjamin Pierce :: Types and Programming Languages :: 46.11 :: true :: HNil | |
noId("id") // Attempting to access a missing field is a compile time error | |
// <console>:25: error: could not find implicit value for parameter selector ... | |
// noId("id") |
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
def row(cols : Seq[String]) = cols.mkString("\"", "\",\"", "\"") | |
//> row: (cols: Seq[String])String | |
// Ensures number of items in hdrs and rows is the same. Magic! | |
def csv[N <: Nat] | |
(hdrs : Sized[Seq[String], N], | |
rows : List[Sized[Seq[String], N]]) = row(hdrs) :: rows.map(row(_)) | |
//> csv: [N <: shapeless.Nat](hdrs: shapeless.Sized[Seq[String],N], rows: List[s | |
//| hapeless.Sized[Seq[String],N]])List[String] | |
val hdrs = Sized("Title", "Author") //> hdrs : shapeless.Sized[scala.collection.immutable.IndexedSeq[String],shapel | |
//| ess.nat._2] = shapeless.Sized@b45d9d5e | |
val rows = List( | |
Sized("Types and Programming Languages", "Benjamin Pierce"), | |
Sized("The Implementation of Functional Programming Languages", "Simon Peyton-Jones") | |
) //> rows : List[shapeless.Sized[scala.collection.immutable.IndexedSeq[String],s | |
//| hapeless.nat._2]] = List(shapeless.Sized@32bb6d1f, shapeless.Sized@15b5dd24) | |
//| | |
// hdrs and rows statically known to have the same number of columns | |
val formatted = csv(hdrs, rows) // Compiles | |
//> formatted : List[String] = List("Title","Author", "Types and Programming La | |
//| nguages","Benjamin Pierce", "The Implementation of Functional Programming La | |
//| nguages","Simon Peyton-Jones") | |
// extendedHdrs has the wrong number of columns for rows | |
val extendedHdrs = Sized("Title", "Author", "ISBN") | |
//> extendedHdrs : shapeless.Sized[scala.collection.immutable.IndexedSeq[String | |
//| ],shapeless.nat._3] = shapeless.Sized@7946158f | |
//val badFormatted = csv(extendedHdrs, rows) // Does not compile |
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
import shapeless._ | |
import poly._ | |
import syntax.std.tuple._ | |
// tuples can now be treated like HList | |
// head, tail, take, drop, split | |
(23, "foo", true).head //> res0: Int = 23 | |
(23, "foo", true).tail //> res1: (String, Boolean) = (foo,true) | |
(23, "foo", true).drop(2) //> res2: (Boolean,) = (true,) | |
(23, "foo", true).take(2) //> res3: (Int, String) = (23,foo) | |
//splits at 1st element | |
(23, "foo", true).split(1) //> res4: ((Int,), (String, Boolean)) = ((23,),(foo,true)) | |
//Wont' even compile as don't have that many elements in tuple. V type safe | |
//(23, "foo", true).split(4) | |
// prepend, append, concatenate | |
23 +: ("foo", true) //> res5: (Int, String, Boolean) = (23,foo,true) | |
(23, "foo") :+ true //> res6: (Int, String, Boolean) = (23,foo,true) | |
(23, "foo") ++ (true, 2.0) //> res7: (Int, String, Boolean, Double) = (23,foo,true,2.0) | |
// map, flatMap | |
object option extends (Id ~> Option) { | |
def apply[T](t: T) = Option(t) | |
} | |
(23, "foo", true) map option //> res8: (Option[Int], Option[String], Option[Boolean]) = (Some(23),Some(foo),S | |
//| ome(true)) | |
((23, "foo"), (), (true, 2.0)) flatMap identity //> res9: (Int, String, Boolean, Double) = (23,foo,true,2.0) | |
object size extends Poly1 { | |
implicit def caseInt = at[Int](x => 1) | |
implicit def caseString = at[String](_.length) | |
implicit def caseTuple[T, U] | |
(implicit st : Case.Aux[T, Int], su : Case.Aux[U, Int]) = | |
at[(T, U)](t => size(t._1)+size(t._2)) | |
} | |
object addSize extends Poly2 { | |
implicit def default[T](implicit st: size.Case.Aux[T, Int]) = | |
at[Int, T]{ (acc, t) => acc+size(t) } | |
} | |
// fold | |
(23, "foo", (13, "wibble")).foldLeft(0)(addSize) //> res10: Int = 11 | |
// conversion to `HList`s and ordinary Scala `List`s | |
(23, "foo", true).productElements //> res11: shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeless. | |
//| HNil]]] = 23 :: foo :: true :: HNil | |
(23, "foo", true).toList //> res12: List[Any] = List(23, foo, true) | |
// zipper | |
import syntax.zipper._ | |
(23, ("foo", true), 2.0).toZipper.right.down.put("bar").root.reify | |
//> res13: (Int, (String, Boolean), Double) = (23,(bar,true),2.0) | |
// index into tuple | |
val t = (23, "foo", true) //> t : (Int, String, Boolean) = (23,foo,true) | |
t(1) //> res1: String = foo | |
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
// Typesafe cast, return Option, not exception on fail | |
import syntax.typeable._ | |
val l: Any = List(Vector("foo", "bar", "baz"), Vector("wibble")) | |
//> l : Any = List(Vector(foo, bar, baz), Vector(wibble)) | |
l.cast[List[Vector[String]]] //> res0: Option[List[Vector[String]]] = Some(List(Vector(foo, bar, baz), Vector | |
//| (wibble))) | |
l.cast[List[Vector[Int]]] //> res1: Option[List[Vector[Int]]] = None | |
l.cast[List[List[String]]] //> res2: Option[List[List[String]]] = None | |
//TypeCases to retain type info | |
//Backticks to allow for odd value names | |
val `List[String]` = TypeCase[List[String]] //> List[String] : shapeless.TypeCase[List[String]] = shapeless.TypeCase$$anon$ | |
//| 16@61dc03ce | |
val `List[Int]` = TypeCase[List[Int]] //> List[Int] : shapeless.TypeCase[List[Int]] = shapeless.TypeCase$$anon$16@50f | |
//| 8360d | |
val l2 = List(5, 10, 15) //> l2 : List[Int] = List(5, 10, 15) | |
(l2: Any) match { | |
case `List[String]`(List(s, _*)) => s.length | |
case `List[Int]`(List(i, _*)) => i+1 | |
} //> res3: Int = 6 | |
vs | |
// type erasure strikes again! Matches first case, even though List of Int | |
l2 match { | |
case s:List[String]=>s.length | |
case x:List[Int]=>x.head+1 | |
} //> res4: Int = 3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment