Подтвердить что ты не робот

Функциональное программирование реального мира в Scala

Тааак...

Полугруппы, моноиды, монады, функторы, линзы, катаморфизмы, анаморфизмы, стрелы... Все это хорошо, и после упражнения или двух (или десяти) вы можете понять их сущность. И с Scalaz вы получаете их бесплатно...

Однако, с точки зрения реального программирования, я изо всех сил пытаюсь найти применение этих понятий. Да, конечно, я всегда нахожу кого-то в сети, используя Monads для IO или Lenses в Scala, но... еще...

То, что я пытаюсь найти, - это что-то вроде "предписывающих" строк шаблона. Что-то вроде: "здесь вы пытаетесь решить эту проблему, и один хороший способ ее решить - использовать линзы таким образом!"

Предложения?


Обновление: что-то в этих строках, с книгой или двумя, было бы замечательно (спасибо Paul): Примеры шаблонов дизайна GoF в основных библиотеках Java

4b9b3361

Ответ 1

Я сказал в сентябре, посвященный практическому применению моноидов и аппликативных функторов/монад посредством scalaz.Validation. Я дал еще одну версию того же сообщения в scala Lift Off, где акцент был сделан скорее на валидации. Я бы посмотрел первый разговор, пока не начну проверку, а затем перейду ко второму разговору (27 минут).

Там также текст, который я написал, который показывает, как вы можете использовать Validation в "практическом" приложении. То есть, если вы разрабатываете программное обеспечение для новичков-вышибалов.

Ответ 2

Ключом к функциональному программированию является абстракция и возможность абстракции. Monads, Arrows, Lenses, все это абстракции, которые оказались полезными, главным образом потому, что они являются составными. Вы попросили "предписывающий" ответ, но я скажу "нет". Возможно, вы не уверены, что вопросы функционального программирования?

Я уверен, что многие люди в StackOverflow будут более чем счастливы попробовать и помочь решить конкретную проблему по пути FP. Есть список вещей, и вы хотите пройти список и создать какой-то результат? Используйте складку. Хотите разобрать XML? hxt использует для этого стрелки. И монады? Ну, тонны типов данных оказываются Монадами, поэтому узнайте о них, и вы обнаружите множество способов управления этими типами данных. Но из-за этого трудно просто вытащить примеры из воздуха и сказать, что "линзы - это правильный способ сделать это", "моноиды - лучший способ сделать это" и т.д. Как бы вы объяснили новичку, что использование цикл for? Если вы хотите [пусто], используйте цикл for [таким образом]. Это так общее; существует множество способов использования цикла for. То же самое касается этих абстракций FP.

Если у вас много лет опыта ООП, то не забывайте, что вы когда-то были новичком в ООП. Требуется время, чтобы изучить способ FP и еще больше времени, чтобы разукрасить тенденции ООП. Дайте ему время, и вы найдете множество применений для функционального подхода.

Ответ 3

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

Как только вы начнете с этого маршрута, вы можете увидеть использование везде. Для меня я получаю полугруппы, моноиды, монады, функторы. Так что возьмите пример ответа на этот вопрос Как заполнить список объектов новыми значениями. Это реальное использование для человека, задающего вопрос (самостоятельно описываемый noob). Я пытаюсь ответить простым способом, но я должен воздержаться от поцарапания зуда "здесь есть моноиды".

Теперь поцарапать его: используя foldMap и тот факт, что Int и List являются моноидами и что свойство monoid сохраняется при работе с кортежем, картами и опциями:

// using scalaz
listVar.sliding(2).toList.foldMap{
  case List(prev, i) => Some(Map(i -> (1, Some(List(math.abs(i - prev))))))
  case List(i) => Some(Map(i -> (1, None)))
  case _ => None
}.map(_.mapValues{ case (count, gaps) => (count, gaps.map(_.min)) })

Но я не прихожу к этому результату, думая, что буду использовать жесткое функциональное программирование. Это происходит более естественно, если подумать, что это проще, если я сочиняю эти моноиды в сочетании с тем фактом, что у scalaz есть полезные методы, такие как foldMap. Интересно, глядя на полученный код, не очевидно, что я полностью думаю о моноидах.

Ответ 4

Вам может понравиться этот разговор от Криса Маршалла. Он охватывает пару лаконичных материалов Scalaz - Monoid и Validation - со многими практическими примерами. Ittay Dror написал очень доступный пост о том, как Functor, Applicative Functor и Monad могут быть полезны на практике. Эрик Торреборр и Debasish Gosh в блогах также есть куча сообщений охватывающих варианты использования категориальных конструкций.

В этом ответе мы просто перечисляем несколько ссылок, а не предоставляем здесь какое-то реальное содержание. (Слишком ленив, чтобы писать.) Надеюсь, вам все равно будет полезно.

Ответ 5

Я понимаю вашу ситуацию, но вы обнаружите, что для изучения функционального программирования вам нужно будет настроить свою точку зрения на документацию, которую вы найдете, а не наоборот. К счастью, в Scala у вас есть возможность постепенно стать функциональным программистом.

Чтобы ответить на ваши вопросы и объяснить разницу в точках зрения, мне нужно различать "типы классов" (моноиды, функторы, стрелки), математически называемые "структуры" и общие операции или алгоритмы (катаморфизм или складки, анаморфизм или разворот и т.д.). Эти два часто взаимодействуют, поскольку многие общие операции определены для определенных классов типов данных.

Вы ищете предписывающие ответы, похожие на шаблоны проектирования: когда применяется эта концепция? Правда в том, что вы наверняка видели предписывающие ответы, и они просто являются определениями различных понятий. Проблема (для вас) заключается в том, что эти ответы по сути отличаются от шаблонов проектирования, но это по уважительным причинам.

С одной стороны, общие алгоритмы не являются шаблонами проектирования, которые предполагают структуру для кода, который вы пишете; это абстракции, определенные на языке, который вы можете применить непосредственно. Они являются общими описаниями общих алгоритмов, которые вы уже реализуете сегодня, но вручную. Например, всякий раз, когда вы вычисляете максимальный элемент списка, сканируя его, вы жестко кодируете сгиб; когда вы суммируете элементы, вы делаете то же самое; и так далее. Когда вы это узнаете, вы можете объявить суть операции, которую вы выполняете, вызвав соответствующую функцию сгиба. Таким образом, вы сохраняете код и ошибки (нет возможности для ошибок "один за другим" ), и вы сохраняете читателя в попытке прочитать весь необходимый код.

С другой стороны, структуры относятся не к цели, которую вы имеете в виду, а к свойствам объектов, которые вы моделируете. Они более полезны для построения программного обеспечения снизу вверх, а не сверху вниз: при определении ваших данных вы можете заявить, что это, например, моноид. Позже, при обработке ваших данных, у вас есть возможность использовать операции, например. моноиды для реализации вашей обработки. В некоторых случаях полезно стремиться выразить свой алгоритм с точки зрения предопределенных. Например, очень часто, если вам нужно уменьшить дерево до одного значения, фолд может делать больше всего или все, что вам нужно. Конечно, вы также можете заявить, что ваш тип данных является моноидом, когда вам нужен общий алгоритм для моноидов; но чем раньше вы заметите, что раньше вы можете начать повторное использование общих алгоритмов для моноидов.

Последний совет заключается в том, что, вероятно, большая часть документации, которую вы найдете об этих концепциях, относится к Haskell, потому что этот язык существует гораздо больше времени и поддерживает их довольно элегантно. Настоятельно рекомендуется здесь Учить вас Haskell для Great Good, курс Haskell для начинающих, где среди других глав 11-14 посвящены некоторые классы классов, и Typeclassopedia (который содержит ссылки на различные статьи с конкретными примерами). EDIT: Наконец, пример приложений моноидов, взятых из Typeclassopedia, находится здесь: http://apfelmus.nfshost.com/articles/monoid-fingertree.html. Я не говорю, что есть небольшая документация для Scala, просто в Haskell больше, а Haskell - это то, где появилось приложение этих понятий к программированию.