Что-то поперло
про type classes, просто поперло.
Только на днях
я упоминал зачетные слайды
https://speakerdeck.com/raulraja/typeclasses-tour
Не прошло и
недели, как мне попадается изумительный
материал про тайп классы
Настолько все
доступно изложено, что даже я всё понял.
И применил на
практике:
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
// type classes example | |
// based on material from SICP 1.3.1 high-order procedures | |
// inspired by | |
// The Neophyte's Guide to Scala Part 12: Type Classes | |
// http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html | |
// scala.math.Numeric is a type class | |
// that define an interface | |
// abstract numeric increment (can be int, can be double) | |
def inc[T : Numeric](x: T) = implicitly[Numeric[T]].plus(x, implicitly[Numeric[T]].one) | |
// one way to access an implicit value | |
// abstract numeric cube | |
def cube[T](x: T)(implicit ev: Numeric[T]) = ev.times(x, ev.times(x, x)) | |
// another way to access | |
// abstract sum for abstract sequence | |
def sum[T](op: T => T, | |
a: T, | |
next: T => T, | |
b: T) | |
(implicit ev: Numeric[T]): T = { | |
if (ev.gt(a, b)) ev.zero | |
else ev.plus(op(a), sum(op, next(a), next, b)) | |
} | |
// int | |
def sumCubes(a: Int, b: Int): Int = sum[Int](cube[Int], a, inc[Int], b) | |
sumCubes(1, 10) // 3025 | |
def sumIntegers(a: Int, b: Int): Int = sum[Int](identity, a, inc[Int], b) | |
sumIntegers(1, 10) // 55 | |
// double | |
def piterm(x: Double): Double = 1.0 / (x * (x + 2)) | |
def pinext(x: Double): Double = x + 4 | |
def piSum(a: Int, b: Int): Double = sum[Double](piterm, a, pinext, b) | |
piSum(1, 1000) * 8 // 3.139 | |
// or, you can cast int to double and forget about Numeric type class | |
def alldouble() = { | |
def cube(x: Double): Double = x * x * x | |
def inc(n: Double): Double = n + 1 | |
def sum(op: Double => Double, | |
a: Double, | |
next: Double => Double, | |
b: Double): Double = { | |
if (a > b) 0 | |
else op(a) + sum(op, next(a), next, b) | |
} | |
def sumCubes(a: Int, b: Int) = sum(cube, a, inc, b) | |
println(sumCubes(1, 10)) // 3025.0 | |
def sumIntegers(a: Int, b: Int) = sum(identity, a, inc, b) | |
println(sumIntegers(1, 10)) // 55.0 | |
def piterm(x: Double): Double = 1.0 / (x * (x + 2)) | |
def pinext(x: Double): Double = x + 4 | |
def piSum(a: Int, b: Int) = sum(piterm, a, pinext, b) | |
piSum(1, 1000) * 8 // 3.139 | |
} | |
alldouble() |
Идея очень
проста и отвечает на запрос: как нам
облегчить ad-hoc polymorphism в системах со
строгой типизацией? Нужно абстрагировать
некий алгоритм, повысить степень DRY.
Ну как, делаем
интерфейс, реализуем алгоритм в терминах
этого интерфейса. Реализацию интерфейса
подмешиваем в нужный класс – опля, этот
класс можно пихать в упомянутый алгоритм.
Проверка типов
в Scala делается через implicit переменные.
Повторюсь: как
же люди без дактайпинга мучаются. Зато
всё под контролем.
original post http://vasnake.blogspot.com/2016/07/scala-type-classes.html
original post http://vasnake.blogspot.com/2016/07/scala-type-classes.html
Комментариев нет:
Отправить комментарий