Last active
December 26, 2015 10:29
-
-
Save milessabin/7136706 to your computer and use it in GitHub Desktop.
My crib sheet from the shapeless workshop @ Scala IO.
This file contains 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
package scalaio | |
import shapeless._, poly._ | |
object list extends (Id ~> List) { | |
def apply[T](t : T) = List(t) | |
} | |
object headOption extends (List ~> Option) { | |
def apply[T](l : List[T]) = l.headOption | |
} | |
object plus extends Poly2 { | |
implicit val caseInt = at[Int, Int](_ + _) | |
} | |
object inc extends ->((i: Int) => i+1) | |
object hinc extends Poly1 { | |
implicit val caseInt = at[Int](_+1) | |
implicit val caseString = at[String](_+"*") | |
implicit val caseBoolean = at[Boolean](!_) | |
} | |
object TupleDemo { | |
import syntax.std.tuple._ | |
val t = (23, "foo", true) | |
// Heads and tails | |
t.head | |
t.tail | |
t.last | |
t.init | |
// : t t.tail.tail.tail ... Unit | |
// Come back to indexing/updating/splitting | |
// Append, prepend, concat | |
1.0 +: t | |
t :+ 1.0 | |
val u = (1.0, 'a') | |
t ++ u | |
() ++ t == t // tuples are monoids wrt Unit and ++ | |
t ++ () == t | |
// map, flatMap | |
val t1 = t map list | |
t1 map headOption | |
val v = ((23, "foo"), (), (1.0, true, 'c')) | |
v flatMap identity | |
val w = (1, 2, 3, 4, 5) | |
w.foldLeft(0)(plus) | |
// zip, unzip, transpose | |
val x = ((23, "foo"), (true, 1.0), ('c', 13)) | |
val x1 = x.zip | |
val x2 = x1.unzip | |
x.transpose // .transpose.transpose | |
val v0 = (1.0, 0.0, 0.0) | |
val v1 = (2.0, 3.0, 0.0) | |
val v2 = (4.0, 5.0, 6.0) | |
val m = (v0, v1, v2) | |
m.transpose | |
// toList | |
v0.toList | |
// productElements | |
t.productElements | |
} | |
object GenericDemo { | |
case class Address(street: String, number: Int, city: String, country: String) | |
case class Person(name: String, age: Int, address: Address) | |
val suesAddress = Address("North Street", 23, "Brighton", "UK") | |
val sue = Person("Sue", 32, suesAddress) | |
val pgen = Generic[Person] | |
val agen = Generic[Address] | |
// to | |
agen.to(suesAddress) | |
pgen.to(sue) | |
// from | |
val johnsAddressl = "South Street" :: 13 :: "Bristol" :: "UK" :: HNil | |
val johnsAddress = agen.from(johnsAddressl) | |
val johnl = "John" :: 31 :: johnsAddress :: HNil | |
val john = pgen.from(johnl) | |
// low level slicing and dicing | |
val mtownl = agen.to(pgen.to(sue).tail.tail.head).drop(2) | |
val jstreetl = agen.to(pgen.to(john).tail.tail.head).take(2) | |
val fixedl = jstreetl ++ mtownl | |
val fixed = agen.from(fixedl) | |
// Lenses | |
val streetLens = Lens[Person] >> 2 >> 0 | |
streetLens.get(john) | |
streetLens.set(john)("East Street") | |
// Zipper | |
import Zipper._ | |
val jz = john.toZipper | |
jz.right.right.down.put("West Street").root.reify | |
// Coproducts, Scrap Your Boilerplate, recursion | |
sealed trait Tree[T] | |
case class Leaf[T](t: T) extends Tree[T] | |
case class Node[T](left: Tree[T], right: Tree[T], name: String = "Foo") extends Tree[T] | |
Generic[Leaf[Int]] | |
Generic[Node[Int]] | |
Generic[Tree[Int]] // Abstract, recursive | |
// Compare: product | |
val isb = 23 :: "foo" :: true :: HNil | |
isb map hinc | |
everywhere(hinc)(isb) | |
// Compare: coproduct/sum | |
type ISB = Int :+: String :+: Boolean :+: CNil | |
val i = Coproduct[ISB](23) | |
val s = Coproduct[ISB]("foo") | |
val b = Coproduct[ISB](true) | |
i map hinc | |
s map hinc | |
b map hinc | |
everywhere(hinc)(i) | |
everywhere(hinc)(s) | |
everywhere(hinc)(b) | |
// Sum of products ... with recursion! | |
val tree: Tree[Int] = | |
Node( | |
Node( | |
Node( | |
Leaf(1), | |
Node( | |
Leaf(2), | |
Leaf(3) | |
) | |
), | |
Leaf(4) | |
), | |
Node( | |
Leaf(5), | |
Leaf(6) | |
) | |
) | |
everywhere(inc)(tree) | |
} | |
object SingletonDemo { | |
val foo = "foo" | |
val foo2 : foo.type = foo // nb. not "foo" | |
// No 23.type/"foo".type/true.type | |
import syntax.singleton._ | |
23.narrow | |
"foo".narrow | |
true.narrow | |
val wFoo = Witness("foo") | |
val wBar = Witness("bar") | |
val wBaz = Witness("baz") | |
type Foo = wFoo.T | |
type Bar = wBar.T | |
type Baz = wBaz.T | |
val w0 = Witness(0) | |
val w1 = Witness(1) | |
val w2 = Witness(2) | |
type _0 = w0.T | |
type _1 = w1.T | |
type _2 = w2.T | |
val wT = Witness(true) | |
val wF = Witness(false) | |
type True = wT.T | |
type False = wF.T | |
// Type classes indexed by values | |
trait Choose[B <: Boolean, T] { | |
def apply() : T | |
} | |
object Choose { | |
implicit val chooseTrue = new Choose[True, String] { | |
def apply() = "Foo" | |
} | |
implicit val chooseFalse = new Choose[False, Int] { | |
def apply() = 23 | |
} | |
} | |
def choose[T](b: Witness.Lt[Boolean])(implicit choose: Choose[b.T, T]): T = choose() | |
// HLists and tuples indexed by Int literals | |
object Index { | |
import syntax.std.tuple._ | |
val t = (23, "foo", true) | |
t(1) | |
t.updatedAt(1, 2.0) | |
t.split(1) | |
val l = 23 :: "foo" :: true :: HNil | |
l(1) | |
l.updatedAt(1, 2.0) | |
l.split(1) // ._1, ._2 vs. resX(0), resX(1) | |
} | |
// Records with singleton literal keys | |
import record._, syntax.singleton._ | |
val field = "foo" -> 23 | |
val sfield = "foo" ->> 23 | |
def value[K, V](f: FieldType[K, V]): V = f | |
def key[K, V](f: FieldType[K, V])(implicit wKey: Witness.Aux[K]): K = wKey.value | |
val book = | |
("author" ->> "Benjamin Pierce") :: | |
("title" ->> "Types and Programming Languages") :: | |
("id" ->> 262162091) :: | |
("price" ->> 44.99) :: | |
HNil | |
book("author") | |
book("price") | |
val book1 = book + ("price" ->> 39.99) | |
book("price") | |
book.values // .tupled | |
book.keys // .tupled | |
} | |
object IllTypedDemo { | |
import test.illTyped | |
//illTyped(""" 23 : Int """) | |
illTyped(""" 23 : String """) | |
//val liar : Unit = illTyped(""" liar """) | |
} | |
// Sized take and drop |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment