Почему использование Maybe/Option не настолько распространено в Clojure?

Почему Clojure, несмотря на такой акцент на функциональную парадигму, не использовать монаду Maybe/Option для представления необязательных значений? Использование Option довольно распространено в Scala, языке функционального программирования, который я использую регулярно.

+37
источник поделиться
6 ответов

Clojure не статически типизирован, поэтому не нужно строгое это/что/любые объявления типов, которые необходимы в haskell (и, я собираюсь, Scala). Если вы хотите вернуть строку, вы возвращаете строку; если вместо этого вы вернете нуль, это тоже хорошо.

"Функциональный" не соответствует точно "строгой компиляции времени". Они являются ортогональными понятиями, а Clojure выбирает динамическую типизацию. Фактически, довольно долго я не мог себе представить, как вы могли бы реализовать многие функции более высокого порядка, такие как map и по-прежнему сохранять статическую типизацию. Теперь, когда у меня есть небольшой (очень маленький) опыт работы с Haskell, я вижу, что это возможно, и действительно часто довольно элегантно. Я подозреваю, что если вы некоторое время играете с Clojure, у вас будет противоположный опыт: вы поймете, что объявления типа не нужны, чтобы дать вам такую ​​мощь, какую вы использовали на функциональном языке.

+45
источник

В Clojure nil punning предоставляет большую часть функциональных возможностей, которые Scala и Haskell получают из Option и Maybe.

**Scala**                **Clojure**
Some(1) map (2+_)        (if-let [a 1] (+ 2 a))

Some(1) match {          (if-let [a 1]
  case Some(x) => 2+x      (+ 2 a)
  case None    => 4        4)
}

Scala Опция и Haskell Возможно, оба экземпляра Аппликативные. Это означает, что вы можете использовать значения этих типов в понимании. Например, Scala поддерживает:

for { a <- Some(1)
      b <- Some(2)
} yield a + b

Clojure для макросов предоставляет понимание по seq. В отличие от монадических понятий, эта реализация позволяет смешивать типы экземпляров.

Хотя Clojure для не может использоваться для составления функций по нескольким возможным значениям nil, это функциональность, которую тривиально реализовать.

(defn appun [f & ms]
  (when (every? some? ms)
    (apply f ms)))

И назвав его:

(appun + 1 2 3)    #_=> 6
(appun + 1 2 nil)  #_=> nil
+20
источник

Может быть/Опция - это тип. Это не имеет никакого отношения к функциональному программированию. Да, некоторые языки (Scala, haskell, ocaml) помимо функциональности также обеспечивают очень мощную систему типов. Люди даже говорят о haskell, что это программирование С ТИПАМИ.

Другие (clojure, lisp) не обеспечивают многого с точки зрения типов, даже если они полностью функциональные языки. Их акцент различен, и тип Maybe/Option не подходит. Он просто не дает вам многого в динамическом языке. Например, многие функции clojure, работающие над последовательностями (списки, векторы, карты), прекрасно принимают значение null (nil) и рассматривают его как пустую структуру.

(count nil) даст вам 0. Точно так же (count [])

Clojure нельзя назвать "программированием с типами", и, следовательно, тип Maybe не имеет особого смысла.

+12
источник

Важно помнить, что концепция Монады не относится к типам! Типовые системы помогают вам применять правила (но даже Haskell не может применять все правила, поскольку некоторые из них (законы Монады) не могут быть полностью выражены системой типов.

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

Тип Maybe - это объединение длинных последовательностей вычислений вместе, не говоря уже о неудаче (что является "дополнительным контекстом" ). Это шаблон, который перемещает "обработку ошибок" из вычислений и в Monad. Вы можете выставить последовательность вычислений на Maybe, и как только один провалится, остальные будут проигнорированы, а окончательный результат - "ничего". Если все они преуспевают, то ваш конечный результат - это монада, удерживающая значение результата.

Это позволяет вам писать код, который гораздо менее запутан.

Clojure поддерживает Monads, как отметил @deterb.

+9
источник

Ну, возможно, монада Maybe, но она использует nil как Nothing, захватывая только абстракцию вычисления (если input = nil return nil else calc any with input), чтобы избежать ошибок с нулевыми указателями, но у нее нет статической безопасности во время компиляции, Существует fnil, который имеет аналогичную задачу, исправляя нуль со значениями по умолчанию и . Я думаю, что способ clojure более ориентирован на возврат значений по умолчанию, которые вызывают ошибки или ноль.

+7
источник

Переход с @amalloy и комментариями, что Clojure, как язык, не нуждается в необязательном возвращаемом значении.

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

Я быстро просмотрел библиотеку Clojure -Contrib, и у них есть monad package, который вы можете посмотреть. Другой элемент, который действительно показал мне, как можно использовать Monads в Clojure, учебник Cosmin по Monads в Clojure. Именно это помогло мне связать, как функциональность, указанная более явно в Scala, обрабатывается как часть динамического языка Clojure.

+4
источник

Посмотрите другие вопросы по меткам или Задайте вопрос