Как пишут моноид на Scala программисты с разным бэкграундом
Спецификация:
Реализация:
Контекстуализация:
// Хаскелист trait Monoid[T] { val id: T def op: T => T => T } // Эмельщик trait Monoid { type T val id: T def op: (T, T) => T } // Хардкорный эмельщик type MONOID = { type T val id: T def op: (T, T) => T } // Джавист, прочитавший о self-типах trait Monoidal[T] { this: T => def op(x: T): T } // Джавист, прочитавший о имплицитных вьюхах abstract class MonoidEnriched[T] { def op(y: T): T } // Джавист, прочитавший о тайпклассах trait Monoid[T] { val id: T def op(x: T, y: T): T } // Джавист, прочитавший ещё и о карринге и частичном применении trait Monoid[T] { val id: T def op(x: T)(y: T): T }
Реализация:
// Хаскелист implicit def list[T] = new Monoid[List[T]] { val id = Nil def op = xs => xs ++ _ } // Эмельщик implicit def list[E] = new Monoid { type T = List[E] val id = Nil def op = _ ++ _ } // Хардкорный эмельщик implicit def list[E]: MONOID { type T = List[E] } = new { type T = List[E] val id = Nil def op = _ ++ _ } // Джавист, прочитавший о self-типах class MonoidalListAdapter[T](val list: List[T]) extends Monoidal[MonoidalListAdapter[T]] { def op(x: MonoidalListAdapter[T]) = new MonoidalListAdapter[T](list ++ x.list) } // Джавист, прочитавший о имплицитных вьюхах abstract class ListMonoidEnriched[T](x: List[T]) extends MonoidEnriched[List[T]] { def op(y: List[T]) = x ++ y } implicit def list[T](l: List[T]) = new ListMonoidEnriched(l) // Джавист, прочитавший ещё и о имплицитных классах implicit class ListMonoidEnriched[T](x: List[T]) extends MonoidEnriched[List[T]] { def op(y: List[T]) = x ++ y } // Джавист, прочитавший о тайпклассах implicit def list[T] = new Monoid[List[T]] { val id = Nil def op(x: List[T], y: List[T]) = x ++ y } // Джавист, прочитавший ещё и о карринге и частичном применении implicit def list[T] = new Monoid[List[T]] { val id = Nil def op(x: List[T])(y: List[T]) = x ++ y }
Контекстуализация:
// Ребята с тайпклассами def f[M](xs: M)(implicit m: Monoid[M]) = m.op(xs, xs) // или m.op(xs)(xs) // Хардкорный эмельщик def f[M](xs: M)(implicit m: MONOID { type T = M }) = { import m._ op(xs, xs) } // Джавист, прочитавший о self-типах def f[M <: Monoidal[M]](xs: M) = xs.op(xs) // Ребята с имплицитными вьюхами и классами def f[M <% MonoidEnriched[M]](xs: M) = xs.op(xs)