Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Странно что слово полугруппа не произнесено.
Где можно посмотреть код целиком?
Благодарю за gist (на самом деле в статье присутствует весь код, просто оно у меня не собиралось из-за неподходящих версий kotlin'а и jdk) и за статью (поставил бы +, но недостаточно кармы для голосования).
Вопросы:
зачем Order реализует интерфейс Monoid?
ComparatorMonoid::plus — не делает ли данная функция лишние сравнения?
fun interface ComparatorMonoid<A> : Monoid<ComparatorMonoid<A>> {
fun compare(a: A, other: A): Order
override fun plus(rh: ComparatorMonoid<A>) =
ComparatorMonoid<A> { a, other ->
val order = compare(a, other)
when (order) {
Order.EQ -> rh.compare(a, other)
else -> order
}
}
override fun empty() = ComparatorMonoid<A> { _, _ -> Order.EQ }
}
fun interface Function2Monoid<A, B : Monoid<B>> : Monoid<Function2Monoid<A, B>> {
fun invoke(a: A, other: A): B
override fun plus(rh: Function2Monoid<A, B>): Function2Monoid<A, B> =
Function2Monoid { a, other -> invoke(a, other) + rh.invoke(a, other) }
override fun empty() = Function2Monoid<A, B> { a, a1 ->
invoke(a, a1).empty()
}
}
fun <A> Iterable<A>.sort(comparatorMonoid: Function2Monoid<A, Order>) =
sortedWith { a, b -> comparatorMonoid.invoke(a, b).compareValue }
fun <A : Comparable<A>> A.compare(other: A) = when {
this > other -> Order.GT
this == other -> Order.EQ
else -> Order.LT
}
val <A, B : Comparable<B>> ((A) -> B).comparator
get():Function2Monoid<A, Order> = Function2Monoid<A, Order> { a, b ->
invoke(a).compare(invoke(b))
}
расскажите как изменится решение, чтобы отсортировать пользователей не как на скриншоте, а в натуральном порядке (user8, user9, user10, user11)
val <A> ((A) -> String).customComparator
get():Function2Monoid<A, Order> = Function2Monoid<A, Order> { a, other ->
val aString = invoke(a)
val otherString = invoke(other)
//сравниваем значения строк как нам нужно
//возвращаем Order, который нам нужен при сравнении
return@Function2Monoid Order.EQ
}
users.sort(
User::name.stringComparator +
User::address.andThen(Address::city).comparator
).forEach(::println)
Как добавить сортировку по адресу, если у отдельных пользователей адрес может быть не указан?
infix fun <A, B, C> ((A) -> B?).andThen(g: (B) -> C): (A) -> C? = { a: A ->
this(a)?.let(g)
}
val <A, B : Comparable<B>> ((A) -> B?).comparator
get():Function2Monoid<A, Order> = Function2Monoid<A, Order> { a, other ->
val b = invoke(a)
val bOther = invoke(other)
when {
b != null && bOther != null -> b.compare(bOther)
b != null -> Order.GT
bOther != null -> Order.LT
else -> Order.EQ
}
}
val <A, B : Comparable<B>> Lens<A, B>.comparator
get():Function2Monoid<A, Order> = ::get.comparator
val <A, B : Comparable<B>> Optional<A, B>.comparator
get():Function2Monoid<A, Order> = (::getOption andThen Option<B>::orNull).comparator
users.sort(
AppUser.name.comparator +
AppUser.address.city.comparator
).forEach(::println)
Kotlin FP: моноиды и сортировки