1+ package fpspeedrun
2+
3+ import scala .language .higherKinds
4+ import syntax .semigroup ._
5+
6+ trait Monoid [T ] extends SemiGroup [T ] {
7+ def empty : T
8+ }
9+
10+ object Monoid {
11+ def apply [T ](implicit i : Monoid [T ]) = i
12+
13+ object Laws {
14+ def identity [T : Monoid ](x : T ): Boolean = {
15+ (Monoid [T ].empty |+| x) == x &&
16+ (x |+| Monoid [T ].empty) == x
17+ }
18+
19+ def associativity [T : Monoid ](x : T , y : T , z : T ): Boolean = {
20+ ((x |+| y) |+| z) == (x |+| (y |+| z))
21+ }
22+ }
23+
24+ /**
25+ * Функция, похожая на SemiGroup#combineList, но для Monoid.
26+ * В отличие от предыдущей, возвращает не Option[T], а сам T.
27+ * Для пустого списка, возвращает "единицу" в понятиях моноида.
28+ */
29+ def foldList [T : Monoid ](list : List [T ]): T = {
30+ list.foldLeft(Monoid [T ].empty) {
31+ case (sum, next) => sum |+| next
32+ }
33+ }
34+
35+ /**
36+ * #foldList, но с крутым синтаксисом и возможностью через параметр типа передавать
37+ * желаемое поведение.
38+ * Паттерн для синтаксиса называется: partial type application
39+ */
40+ def foldListVia [U [_]] = new FoldListVia [U ]
41+ class FoldListVia [U [_]] {
42+ def apply [T ](list : List [T ])(implicit iso : Iso [T , U [T ]], monoid : Monoid [U [T ]]): T = {
43+ val r = list.foldLeft(monoid.empty) {
44+ (acc, next) => acc |+| iso.wrap(next)
45+ }
46+ iso.unwrap(r)
47+ }
48+ }
49+
50+ // monoid instances
51+ implicit val defaultMonoidInt : Monoid [Int ] = new Monoid [Int ] {
52+ override def empty : Int = 0
53+ override def combine (x : Int , y : Int ): Int = x+ y
54+ }
55+ implicit val sumMonoidInt : Monoid [Sum [Int ]] = new Monoid [Sum [Int ]] {
56+ override def empty : Sum [Int ] = Sum (0 )
57+ override def combine (x : Sum [Int ], y : Sum [Int ]): Sum [Int ] = Sum (x.x + y.x)
58+ }
59+ implicit val prodMonoidInt : Monoid [Prod [Int ]] = new Monoid [Prod [Int ]] {
60+ override def empty : Prod [Int ] = Prod (1 )
61+ override def combine (x : Prod [Int ], y : Prod [Int ]): Prod [Int ] = Prod (x.x * y.x)
62+ }
63+ }
0 commit comments