Skip to content

Instantly share code, notes, and snippets.

@lazyvalue
Created March 11, 2015 20:22
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 lazyvalue/8831270f8b3377e59f49 to your computer and use it in GitHub Desktop.
Save lazyvalue/8831270f8b3377e59f49 to your computer and use it in GitHub Desktop.
Module examples worksheet
// Case classes
// Algebraic Data Types
// Objects
// Currying
// Traits
// Classes
// The Cake
// CASE CLASSES
case class CreepyBug(name: String, numberOfEyes: Int, canBeKilledByFire: Boolean)
// This code is generated for you!
// An actual class.
// The compiler will sometimes try to unify types to Product if you make a mistake.
class CreepyBug(val name: String, val numberOfEyes: Int, val canBeKilledByFire: Boolean)
extends Product {
def toString
def equals
def hashCode
def copy(name = this.name, numberOfEyes = this.numberOfEyes,
canBeKilledByFire = this.canBeKilledByFire) =
new CreepyBug(name, numberOfEyes, canBeKilledByFire)
}
val x = new CreepyBug("creepy")
val z = CreepyBug.apply("creepy")
val y = CreepyBug("creepy")
// A companion object!
object CreepyBug {
def apply(val name: String, val numberOfEyes: Int, val canBeKilledByFire: Boolean) = new CreepyBug(name, numberOfEyes, canBeKilledByFire)
}
object FriendlyBug {
def apply(numberOfEyes: Int) = CreepyBug("friendly", numberOfEyes, true)
}
val w: CreepyBug = FriendlyBug(42)
// ALGEBRAIC DATA TYPES
sealed trait Creature {
val lifeForce = // we will get to this
}
case class CreepyBug(numberOfLegs: Int, numberOfEyes: Int,
canBeKilledByFire: Boolean) extends Creature
case class Lizard(hasScales: Boolean, spits: Boolean) extends Creature
case class Monkey(idol: Idol, sneaky: Boolean, esteem: Int) extends Creature
sealed trait Idol
case object SunIdol extends Idol
case object MoonIdol extends Idol
case object UnderworldIdol extends Idol
// Algebra = (MAX_INT * MAX_INT * 2 [Boolean]) for CreepyBug + (2 * 2) for Lizard + (2 * numIdols * MAX_INT (esteem)) for Monkey
// Our match is total
def findHome(creature: Creature): InputOutput[Home] = creature match {
case CreepyBug(_, eyes, z, a) =>
if(eyes > 42) println("How many eyes you have!")
Ground
case lizard: Lizard => Swamp
case monkey: Monkey => Tree
//case _ => throw new Exception
}
// CURRYING!
object MonkeyTools {
def offering(monkey: Monkey, idol: Idol)(item: Sacrifice): Monkey = {
println("Thanks for the sacrifice! " + item)
monkey.copy(idol = idol)
}
// Ofering can be partially applied. Now this Function can be passed around as a constructor
val fruitBaked: Sacrifice = new Sacrifice
val itemFunction: Sacrifice => Monkey = offering(evilMonkey, MoonIdol)
val result: Monkey = itemFunction(fruitBasket)
// On a side note: you can curry as much as you want
val multiplyThreeNumbers: Int => Int => Int => Int = (w: Int) => (x: Int) => (y: Int) =>( z:Int) => w * x * y * z
}
// Another constructor example
// Really hard to get ahold of these LifeForces
case class LifeForce(good: Int, lawful: Int, powerRating: Int, source: Idol, tetherToTheCosmos: CosmosTether)
// Another definition of lizard
abstract class Lizard(hasScales: Boolean, spits: Boolean) extends Creature {
val lifeForce: LifeForce
}
object Lizard {
def apply(inLifeForce: LifeForce)(hasScales: Boolean, spits: Boolean) = new Lizard(hasScales, spits) {
val lifeForce = inLifeForce
}
}
// Dependency inject Lifeforce at the top
// LifeForce at the top, and then just pass around the rest of the constructor
val myLifeForce = // thousands of years of making a life force
val lizardBuilder: (Boolean, Boolean) => Lizard = Lizard(myLifeForce)
// Our offering example felt incomplete. Let's make it better.
trait AcceptsOffering[T, I] {
def offer(x: T): Blessing
}
object Idols {
implicit val sunIdolFruit = new AcceptsOffering[FruitBasket, SunIdol] {
def offer(x: FruitBasket) = {
println("THANK YOU!")
SunIdol.blessing
}
}
implicit val underworldBugs = new AcceptsOffering[CreepyBug, UnderworldIdol] {
def offer(x: CreepyBug) = {
println("The Underworld is pleased.")
UnderworldIdol.blessing
}
}
}
object OfferingTools {
import Idols._
def offering[T,I](monkey: Monkey, item: T, idol: I)(implicit ao: AcceptsOffering[T, I]): Monkey = {
ao.offer(item)
monkey.copy(idol = idol)
}
val someMonkey: Monkey = Monkey(...)
val someBug: CreepyBug = CreepyBug(...)
// Works!
offering(someMonkey, someFruitBasket, SunIdol)
// Works!
offering(someMonkey, someBug, UnderworldIdol)
// Does not compile!
offering(someMonkey, someBug, SunIdol)
// Does not compile, the Moon Idol is silent!
offering(someMonkey, shinyRock, MoonIdol)
}
// TRAITS
trait Jungle {
val creatures: Set[Creature]
}
val myJungle = new Jungle {
val creatures = Set(someBug)
}
object Jungle {
def apply(inCreatures: List[Creatures]) = new Jungle {
val creatures = Set(inCreatures)
}
}
// Traits offer multiple inheritence.
// An object can have multiple traits.
// Traits can be abstract or partially abstract
// Traits COPY all of their values into whoever they are inheriting.
// Use traits sparingly
// Classes are classes
// A cake is a way of layering in dependencies
trait LifeForceProvider {
val lifeForce: LifeForce
}
trait BugFactoryModule {
val bugFactory: BugFactory
class BugFactory {
def makeABug(lifeForce: LifeForce): CreepyBug
}
}
trait TreeFactoryModule {
val treeFactory: TreeFactory
class TreeFactory {
def makeATree(lifeForce: LifeForce): Tree
}
}
trait MonkeyFactoryModule extends TreeFactoryModule with LifeForceProvider {
val monkeyFactory: MonkeyFactory
class MonkeyFactory {
def makeAMonkey: Monkey
def makeMonkeyWithTree: (Monkey,Tree) = (makeAMonkey, treeFactory.makeATree(lifeForce))
}
}
// THIS IS STILL ABSTRACT!!!
trait Jungle extends LifeForceProvider with BugFactoryModule with TreeFactoryModule with MonkeyFactoryModule{
val myTrees = Range(0, 500).map(_ => makeATree(lifeForce))
val myBugs = Range(0,200).map(_ => makeABug(lifeForce))
val monkeys = Range(0,500).map(_ => makeMonkeyWithTree)
}
val aRealJungle = new Jungle with EvilLifeForceProvider with SuperCreepyBugs with DroopyTrees with MoonMonkeys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment