Зависимости функционального программирования: как разделить зависимости между функциями, которые не связаны напрямую - PullRequest
2 голосов
/ 01 мая 2019

эти различные функции скомпонованы вместе, вот так

f1 -> f2 -> f3 -> f4 -> f5

Мне нужно добавить две новые функции fx и fy вокруг f3 следующим образом:

f1 -> f2 -> fx -> f3 -> fy -> f4 -> f5

, поэтому мне нужно предварительнообработать аргумент для f3 и затем обработать вывод из f3

здесь функция fx вносит изменение, и fy возвращает его обратно, но fy нужны дополнительные подробности из fx, чтобы иметь возможность вернуться, чтобы узнать, какие значенияНапример, чтобы вернуться к

, проблема заключается в том, что функция fx должна выдать два выхода

first: output that is needed by f3
second: output that is needed by fy

Вопрос: Как разделить зависимости между функциями, которые не связаны напрямую, существует ли пространственныйспособ / метод решения этой проблемы?

К вашему сведению, я использую Java8

Ответы [ 2 ]

1 голос
/ 22 мая 2019

Я буду использовать некоторый тип A для всех возвращаемых значений функции;вам нужно разобраться с реальными типами самостоятельно.

Вот как вы это описали:

  • Функция fx даст два параметра, назовем их a и b.
  • Функцияf3 обработает значение a и выдаст a'.
  • Наконец, fy будет потреблять a' и b и произведет c.

Давайте посмотрим, как этого добиться (я напишу псевдокод для сигнатур типов):

  1. Определим fy как функцию, которая принимает два параметра и возвращает один:

    (A, A) => A
    
  2. Определите fyp (сокращение от "fy preprocessed") как функцию, которая принимает некоторую функцию предварительной обработки p и выполняет логику вашего fy, но с первым параметром, предварительно обработанным с помощью p.Мы напишем это в виде P => FY, где P - это сигнатура типа функции предварительной обработки, а FY - это сигнатура типа fy:

    P => FY, which expands to  
    (A => A) => (A, A) => A
    

    Итак, реализацияэта функция должна принимать функцию предварительной обработки p типа A => A в качестве входных данных и выполнять логику fy (это справа, (A, A) => A ... обратите внимание на то, как она соответствует сигнатуре fy), но перед выполнением логики он сопоставит первый параметр fy с p.Вот несколько реализаций Scala для справки (я не очень хорош в Java):

    val fyp: (A => A) => ((A, A)) => A =              
      f => fyuParams => performFyLogic((f(fyuParams._1), fyuParams._2))  
    

    , где performFyLogic - фактическая логика обработки вашей fy функции.

  3. Определите окончательную композицию как:

    f1 -> f2 -> fx -> fyp(f3)
    

Вот полная реализация Scala для справки (опять же, Java не очень хорошо знакома):

val f1: Int => Int = _ + 1
val f2: Int => Int = _ + 2
val f3: Int => Int = _ + 3

val fx: Int => (Int, Int) = i => (i + 4, i + 5)

// let's assume that the original fy simply sums up its two parameters
val fyp: (Int => Int) => ((Int, Int)) => Int =
  f => fyArgs => f(fyArgs._1) + fyArgs._2

val composed1 = f1 andThen f2 andThen f3
println(composed1(42)) // 48

val composed2 = f1 andThen f2 andThen fx andThen fyp(f3)
println(composed2(42)) // 102

// because:
// f1 -> f2 -> fx = (42 + 1 + 2 + 4, 41 + 1 + 2 + 5) = (49, 50)
// fyp(f3)((49, 50)) = (49 + 3) + 50 = 102    
1 голос
/ 22 мая 2019

Я решил это, создав функцию fk, которая оборачивает f3, вызывая fx до и fy после нее, таким образом я смог разделить необходимый бит состояния, который похож на стрелки, предложенные Aadit.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...