#kotlin #functional-programming #function-composition
Вопрос:
Я слежу за некоторой видеопрезентацией библиотеки arrow от Kotlin о функциональном программировании. Я пришел к этому примеру композиции функций:
val greaterThanThree = { it > 3 }
val even = { it % 2 == 0 }
val greaterThanThreeAndEven = greaterThanThree compose even
тогда его можно использовать для чего-то вроде:
list.filter(::greaterThanThreeAndEven)
Из моего предыдущего понимания композиции функции следует, что мы передаем параметр первой функции, а затем возвращаемое значение передается второй функции, как в этом примере:
fun compose(f: (Int) -> Boolean, g: (Int) -> Boolean): (Int) -> Boolean = {
x -> f(g(x)) }
Итак, я не знаю, правильно ли я понял, так как я еще не занимался функциональным программированием, но я думал, что шаги будут примерно такими:
val x = 8 передается в Greaterthantree(8) оценивается как -> true>
// тогда меня смущает то, что в соответствии с приведенной выше логикой истина будет передана даже, что не имеет смысладаже(правда)
Может ли кто-нибудь объяснить мне, как составлены эти две функции и каковы шаги для этой результирующей составленной функции:
{ it > 3 amp;amp; it % 2 == 0 }
Комментарии:
1. Можете ли вы сослаться на источник? Я не знаю Котлина, но это не похоже ни на какую функциональную композицию, которую я когда-либо видел….
2. @JaredSmith это видеоурок по библиотеке arrow, где показан пример Greaterthree и даже пример, пример начинается здесь: youtu.be/tM2wEI-e80E?t=157
3. Да, это так… по-другому? Предполагая, что это функции, вы правы в том, что что-то не так, в зависимости от того, как Kotlin относится к булам (на некоторых языках они являются подклассом int), которые либо не должны компилироваться (несоответствие типов), либо будут компилироваться, но давать неправильные ответы.
4. компилируется ли этот код без каких-либо ошибок?
Ответ №1:
compose
это не amp;amp;
так , это цепные вызовы функций.
В тексте определения вашей функции
fun compose(f: (Int) -> Boolean, g: (Int) -> Boolean): (Int) -> Boolean = { x -> f(g(x)) }
g
вызывается с параметром x
, так что x
должно быть an Int
, и g(x)
возвращает a Boolean
.
Однако f
вызывается с возвращаемым значением g
в качестве параметра. Поскольку f
требуется Int
и g
возвращает a Boolean
, компилятор сообщает об ошибке:
error: type mismatch: inferred type is Boolean but Int was expected
Если вы хотите создать логические функции, это может быть примером,
fun booleanCompose(
f: (Int) -> Boolean,
g: (Int) -> Boolean,
op: (Boolean, Boolean) -> Boolean,
): (Int) -> Boolean = {
x -> op(f(x), g(x))
}
val greaterThanThree: (Int) -> Boolean = { it > 3 }
val even: (Int) -> Boolean = { it %2 == 0 }
val and: (Boolean, Boolean) -> Boolean = { b1, b2 -> b1 amp;amp; b2 }
val greaterThanThreeAndEven = booleanCompose(greaterThanThree, even, and)
Чтобы разрешить используемый вами синтаксис, необходима функция расширения с инфиксом:
infix fun ((Int) -> Boolean).and(g: (Int) -> Boolean): (Int) -> Boolean =
booleanCompose(this, g, and)
val greaterThanThreeAndEven = greaterThanThree and even
Комментарии:
1. Да, это выглядит правильно, я действительно был смущен этим примером из учебника arrow, так странно, что они используют примеры, которые даже не могут скомпилироваться, потому что таких новичков, как я, легко спутать с такими неправильными примерами.
2. @Leff Я определенно не считаю себя новичком в FP, и это меня смутило. Я думаю, что это просто сбивает с толку лол.
3. @ДжареДсмит, это утешает