Skip to content

Instantly share code, notes, and snippets.

@erikkaplun
Last active August 29, 2015 14:09
Show Gist options
  • Save erikkaplun/38aa55484d6712e47190 to your computer and use it in GitHub Desktop.
Save erikkaplun/38aa55484d6712e47190 to your computer and use it in GitHub Desktop.
package main
import scala.annotation.implicitNotFound
object DemoWithNaiveSupertype extends App {
trait Addable {
def +(other: Addable): Addable
}
case class Foo(x: Int) extends Addable {
def +(other: Addable) = Foo(x + other.asInstanceOf[Foo].x)
}
case class Bar(x: Int) extends Addable {
def +(other: Addable) = Bar(x + other.asInstanceOf[Bar].x)
}
def doAdd(a: Addable, b: Addable) = println(a + b)
doAdd(Foo(1), Foo(2))
doAdd(Bar(1), Bar(2))
doAdd(Bar(1), Foo(2)) // runtime error
}
object DemoWithParametrizedSupertype extends App {
trait Addable[T] { self: T =>
def +(other: T): T
}
// ei kompileeruks `self: T =>` nõude tõttu:
// class B
// class A extends Addable[B]
case class Foo(x: Int) extends Addable[Foo] {
def +(other: Foo) = Foo(x + other.x)
}
case class Bar(x: Int) extends Addable[Bar] {
def +(other: Bar) = Bar(x + other.x)
}
def doAdd[T <: Addable[T]](a: T, b: T) =
println(a + b)
doAdd(Foo(1), Foo(2))
doAdd(Bar(1), Bar(2))
// doAdd(Bar(1), Foo(2))
}
object DemoWithTypeClass extends App {
case class Foo(x: Int)
case class Bar(x: Int)
case class Baz(x: String)
@implicitNotFound("Don't know how to add values of type ${T}")
trait HowToAdd[T] { def plus(a: T, b: T): T }
implicit val howToAddFoo = new HowToAdd[Foo] {
def plus(a: Foo, b: Foo) = Foo(a.x + b.x)
}
implicit val howToAddBar = new HowToAdd[Bar] {
def plus(a: Bar, b: Bar) = Bar(a.x + b.x)
}
// implicit val howToAddBaz = new HowToAdd[Baz] {
// def plus(a: Baz, b: Baz) = Baz(a.x + " " + b.x)
// }
def doAdd[T](a: T, b: T)(implicit num: HowToAdd[T]): T =
num.plus(a, b)
val a = doAdd(Foo(1), Foo(2))
val b = doAdd(Bar(1), Bar(2))
// doAdd(Baz("Hello"), Baz("World!"))
/****************************/
// implicit class NumericOps[T](x: T)(implicit num: Addable[T]) {
// def +(other: T) = num.plus(x, other)
// }
// Baz("Hello") + Baz("World!")
}
object TypedValidationDemo extends App {
sealed trait AgeCategory
case object Infant extends AgeCategory
case object Toddler extends AgeCategory
case object Teen extends AgeCategory
case object Adult extends AgeCategory
// constructor on private -- väljastpoolt luua ei saa; ainult juurdekäivast companion object'ist
case class Age private(n: Int)
object Age {
def validAge(n: Int) = 0 <= n && n <= 100
def wrap(n: Int): Option[Age] = if (validAge(n)) Some(Age(n)) else None
def unwrap(age: Age) = age.n
}
def ageGroup(age: Age) = {
Age.unwrap(age) match {
case n if 0 <= n && n <= 2 => Infant
case n if n <= 5 => Toddler
case n if n <= 18 => Teen
case n if n >= 18 && n <= 100 => Adult
}
}
val inputAge: Int = 101 // user input
val age = Age.wrap(inputAge)
val category = age.map(ageGroup)
println(category)
}
from __future__ import print_function
# vt. http://en.wikipedia.org/wiki/Algebraic_data_type
def Option(x):
"""Helper x/None väärtuste konvertimiseks Some(x)/Null'iks"""
return Null if x is None else Some(x)
class Some(object):
def __init__(self, x):
self.x = x
def __iter__(self):
return iter([self.x])
# def map(self, fn):
# return Some(fn(self.x))
def __str__(self): return "Some(%s)" % self.x
class Null(object):
def __iter__(self):
return iter([])
# def map(self, fn):
# return Null
def __str__(self):
return "Null"
Null = Null()
def main():
print(map(lambda x: x * 2, Some(4))) # => list
# print(Some(4).map(lambda x: x * 2)) # => Option
# sitt validator
# def vali_age(n):
# return n if 0 <= n <= 100 else None
# hea validator
def vali_age(n):
return Some(n) if 0 <= n <= 100 else Null
def calc_age_group(n):
return 'adult'
input_age = 123 # int(raw_input())
age = vali_age(input_age)
age_group = map(calc_age_group, age) # => list
# age_group = age.map(calc_age_group) # => Option
print(age_group)
from __future__ import print_function
HOW_TO_ADD = {}
class Foo(object):
def __init__(self, x):
self.x = x
def __str__(self):
return "Foo(%s)" % self.x
class Bar(object):
def __init__(self, x):
self.x = x
def __str__(self):
return "Bar(%s)" % self.x
class Baz(object):
def __init__(self, x):
self.x = x
def __str__(self):
return "Baz(%s)" % self.x
def do_add(a, b):
assert type(a) == type(b)
try:
adder = HOW_TO_ADD[type(a)]
except KeyError:
raise Exception("don't know how to add values of type %s" % type(a).__name__)
return adder(a, b)
HOW_TO_ADD[Foo] = lambda a, b: Foo(a.x + b.x)
HOW_TO_ADD[Bar] = lambda a, b: Bar(a.x + b.x)
HOW_TO_ADD[Baz] = lambda a, b: Baz(a.x + b.x)
print(do_add(Foo(1), Foo(2)))
print(do_add(Bar(1), Bar(2)))
print(do_add(Baz(1), Bar(2)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment