Что такое монада?

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

Вопреки тому, что я сказал в одном из моих предыдущих комментариев, DATETIME и Поля «TIMESTAMP» ведут себя по-разному. Поля TIMESTAMP (как указывают документы) берут все, что вы отправляете в формате «ГГГГ-ММ-ДД чч: мм: ss», и конвертируете их из текущего часового пояса в UTC. Обратное происходит прозрачно всякий раз, когда вы извлекаете данные. Поля DATETIME не делают этого преобразования. Они берут все, что вы им отправляете, и просто храните их напрямую.

Ни типы DATETIME, ни типы TIMESTAMP не могут точно хранить данные в часовом поясе, который наблюдает за DST. Если вы сохраняете «2009-11-01 01:30:00», поля не имеют возможности различать, какая версия 1:30 вы хотели - версия -04: 00 или -05: 00.

Хорошо, поэтому мы должны хранить наши данные в часовом поясе, отличном от DST (например, UTC). Поля TIMESTAMP не могут точно обрабатывать эти данные по причинам, которые я объясню: если ваша система настроена на часовой пояс DST, то, что вы вкладываете в TIMESTAMP, возможно, не из того, что вы получаете. Даже если вы отправляете данные, которые вы уже конвертировали в UTC, они все равно будут считать данные в вашем локальном часовом поясе и сделать еще одно преобразование в UTC. Этот временной интервал с временным интервалом между локальными и UTC-ответами TIMESTAMP является убыточным, когда ваш часовой пояс наблюдает за DST (поскольку «2009-11-01 01:30:00» отображается в 2 разных возможных раза).

С DATETIME вы можете хранить свои данные в любом часовом поясе, который хотите, и быть уверенным в том, что вы вернете все, что вы его отправляете (вы не получаете принуждение к конверсиям с потерями, которые поля TIMESTAMP навязывают вам). Таким образом, решение заключается в использовании поля DATETIME и перед сохранением в поле конвертировать из вашего системного часового пояса в любую зону, отличную от DST, которую вы хотите сохранить (я думаю, что UTC, вероятно, лучший вариант). Это позволяет вам построить логику преобразования на вашем языке сценариев, чтобы вы могли явно сохранить UTC-эквивалент «2009-11-01 01:30:00 -04: 00» или «» 2009-11-01 01:30: 00 -05: 00 ".

Еще одна важная вещь, которую следует отметить, заключается в том, что математические функции даты и времени MySQL не работают должным образом вокруг границ DST, если вы сохраняете свои даты в DST TZ. для сохранения в UTC.

В двух словах я теперь делаю это:

При извлечении данных из базы данных:

Явно интерпретирую данные из базы данных как UTC за пределами MySQL, чтобы получить точную временную метку Unix. Для этого я использую функцию strtotime () PHP или ее класс DateTime. Она не может быть надежно выполнена внутри MySQL с использованием функций CONVERT_TZ () или UNIX_TIMESTAMP () MySQL, поскольку CONVERT_TZ будет только выведите значение «YYYY-MM-DD hh: mm: ss», которое страдает от проблем с неоднозначностью, а UNIX_TIMESTAMP () предполагает, что его вход находится в системном часовом поясе, а не в часовом поясе, в который данные были ВКЛЮЧЕНЫ в (UTC) .

При хранении данных в базе данных:

Преобразуйте дату в точное время UTC, которое вы хотите за пределами MySQL. Например: с помощью класса DateTime PHP вы можете указать «2009-11-01 1:30:00 EST» в отличие от «2009-11-01 1:30:00 EDT», а затем преобразовать его в UTC и сохранить правильное время UTC в поле DATETIME.

Phew. Большое спасибо за вклад и помощь каждого. Надеюсь, это сэкономит кому-то еще некоторые головные боли.

Кстати, я вижу это в MySQL 5.0.22 и 5.0.27

1342
задан 7 revs, 7 users 67% 28 August 2015 в 17:05
поделиться

18 ответов

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

пример был бы для файлового ввода-вывода.

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

2
ответ дан 2 revs, 2 users 73% 28 August 2015 в 17:05
поделиться

На самом деле, вопреки взаимопониманию Монад, они не имеют никакого отношения к состоянию. Монады являются просто путем к переносящимся вещам и предоставляют методы, чтобы сделать операции на обернутом материале, не разворачивая его.

, Например, можно создать тип для обертывания другого в Haskell:

data Wrapped a = Wrap a

Для обертывания материала мы определяем

return :: a -> Wrapped a
return x = Wrap x

, Чтобы выполнить операции без разворачивания, сказать, что у Вас есть функция f :: a -> b, тогда можно сделать это к [1 115] лифт что функция для действия на обернутые значения:

fmap :: (a -> b) -> (Wrapped a -> Wrapped b)
fmap f (Wrap x) = Wrap (f x)

Это обо всех, там должен понять. Однако оказывается, что существует более общая функция, чтобы сделать этот подъем , который является bind:

bind :: (a -> Wrapped b) -> (Wrapped a -> Wrapped b)
bind f (Wrap x) = f x

bind может сделать [больше чем 117], но не наоборот. На самом деле, fmap может быть определен только с точки зрения bind и return. Так, при определении монады.. Вы даете его тип (здесь, это было Wrapped a), и затем скажите, как его return и bind операции работают.

прохладная вещь состоит в том, что это оказывается таким общим шаблоном, что он открывается повсеместно, инкапсулирование состояния чистым способом является только одним из них.

Для хорошей статьи о то, как монады могут использоваться, чтобы представить функциональные зависимости и таким образом управлять порядком оценки, как он, используется в монаде Haskell IO, проверьте IO В .

Что касается понимания монад, не волнуйтесь слишком много об этом. Считайте о них, что Вы находите интересными и не волнуете, не понимаете ли Вы сразу же. Тогда просто дайвинг на языке как Haskell является способом пойти. Монады являются одной из этих вещей, где, понимая струйки в Ваш мозг практикой, однажды Вы просто внезапно понимаете понимание их.

178
ответ дан 2 revs, 2 users 98% 28 August 2015 в 17:05
поделиться

Монада является типом данных, который начинает две операции: >>= (иначе bind) и return (иначе unit). return принимает произвольное значение и создает экземпляр монады с ним. >>= берет экземпляр монады и отображает функцию по нему. (Вы уже видите, что монада является странным видом типа данных, с тех пор на большинстве языков программирования Вы не могли записать функцию, которая принимает произвольное значение и создает тип из него. Монады используют своего рода параметрический полиморфизм .)

В нотации Haskell, интерфейс монады записан

class Monad m where
  return :: a -> m a
  (>>=) :: forall a b . m a -> (a -> m b) -> m b

, Эти операции, как предполагается, подчиняются определенным "законам", но это не ужасно важно: "законы" просто шифруют способ, которым должны вести себя разумные реализации операций (в основном, это >>= и return должно согласиться о том, как значения преобразовываются в экземпляры монады и что >>= ассоциативно).

Монады не являются примерно состоянием и вводом-выводом: они абстрагируют общий шаблон вычисления, которое включает работу с состоянием, вводом-выводом, исключениями и недетерминизмом. Вероятно, самые простые монады для понимания являются типами опции и списками:

instance Monad [ ] where
    []     >>= k = []
    (x:xs) >>= k = k x ++ (xs >>= k)
    return x     = [x]

instance Monad Maybe where
    Just x  >>= k = k x
    Nothing >>= k = Nothing
    return x      = Just x

то, где [] и : конструкторы списка, ++, является оператором конкатенации, и Just, и Nothing эти Maybe конструкторы. Обе из этих монад инкапсулируют общие и полезные шаблоны вычисления на их соответствующих типах данных (обратите внимание, что ни один не имеет никакого отношения к побочным эффектам или вводу-выводу).

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

85
ответ дан 5 revs, 2 users 92% 28 August 2015 в 17:05
поделиться

Но, Вы, возможно, изобрели Монады!

sigfpe говорит:

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

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

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

167
ответ дан 3 revs, 2 users 95% 28 August 2015 в 17:05
поделиться

Необходимо сначала понять, каков функтор. Перед этим поймите функции высшего порядка.

А функция высшего порядка является просто функцией, которая берет функцию в качестве аргумента.

А функтор является любой конструкцией типа T, для которого там существует функция высшего порядка, назовите его map, который преобразовывает функцию типа a -> b (учитывая любые два типа a и b) в функцию T a -> T b. Этот map функция должна также повиноваться законам тождества и составу, таким образом, что следующие выражения возвращают true для всего p и q (нотация Haskell):

map id = id
map (p . q) = map p . map q

, Например, конструктор типа звонил List, функтор, если к нему прилагается функция типа (a -> b) -> List a -> List b, который подчиняется законам выше. Единственная практическая реализация очевидна. Получающееся List a -> List b функция выполняет итерации по данному списку, звоня эти (a -> b) функция для каждого элемента, и возвращает список результатов.

А монада является по существу просто функтором T с двумя дополнительными методами, join , типа T (T a) -> T a, и unit (иногда называемый return, fork, или pure) типа a -> T a. Для списков в Haskell:

join :: [[a]] -> [a]
pure :: a -> [a]

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

можно записать функцию, которая делает map, тогда join. Эта функция вызвана bind, или flatMap, или (>>=), или (=<<). Это обычно, как пример монады приведен в Haskell.

монада А должна удовлетворить определенные законы, а именно, это join должно быть ассоциативно. Это означает, что, если у Вас есть значение x из типа [[[a]]] тогда join (join x), должен равняться join (map join x). И pure должны быть идентификационные данные для [1 138] таким образом что join (pure x) == x.

75
ответ дан 10 revs, 3 users 97% 28 August 2015 в 17:05
поделиться

Если я понял правильно, IEnumerable получен из монад. Интересно, могло ли это быть интересным углом сближения для тех из нас от мира C#?

Если это имеет значение, вот некоторые ссылки на учебные руководства, которые помогли мне (и не, я все еще не понял то, что монады).

5
ответ дан Benjol 28 August 2015 в 17:05
поделиться

(См. также ответы по телефону , Что такое монада? )

А хорошая мотивация к Монадам является sigfpe (Dan Piponi) , Вы, Возможно, Изобрели Монады! (И Возможно Вы Уже Имеете) . Существуют МНОГО других учебных руководств по монаде , многие из которых ошибочно пытаются объяснить монады в "простых терминах" использование различных аналогий: это учебная ошибка монады ; избегайте их.

Как DR MacIver говорит в , Говорят нам, почему Ваш язык сосет :

Так, вещи я ненавижу о Haskell:

Let’s запускаются с очевидного. Учебные руководства по монаде. Нет, не монады. Конкретно учебные руководства. They’re бесконечный, раздутый и дорогой бог являются ими утомительный. Далее, I’ve, никогда замечаемый любое убедительное доказательство, что они на самом деле помогают. Считайте определение класса, запишите некоторый код, преобладайте над страшным именем.

Вы говорите, что понимаете, Возможно, монада? Хороший, Вы на пути. Только начните использовать другие монады, и рано или поздно Вы поймете то, что монады в целом.

[Если Вы математически ориентированы, Вы могли бы хотеть проигнорировать десятки учебных руководств и изучить определение или следовать лекции в теории категорий :) Основная часть определения - то, что Монада M вовлекает "конструктора типа", который определяет для каждого существующего типа "T" новый тип "M T" и некоторые пути к движению назад и вперед между "регулярными" типами и типами "M".]

кроме того, удивительно достаточно, одно из лучших введений в монады является на самом деле одной из ранних научных работ, представляющих монады, Philip Wadler Монады для функционального программирования . Это на самом деле имеет практичный, нетривиальный примеры мотивации, в отличие от многих искусственных учебных руководств там.

34
ответ дан 5 revs, 2 users 69% 28 August 2015 в 17:05
поделиться

[Правовая оговорка: Я все еще пытаюсь полностью grok монады. Следующее, что я понял до сих пор. Если it’s неправильно, надо надеяться, кто-то хорошо осведомленный позвонит мне на ковре.]

Arnar записал:

Монады являются просто путем к переносящимся вещам и предоставляют методы, чтобы сделать операции на обернутом материале, не разворачивая его.

That’s точно это. Идея идет как это:

  1. Вы принимаете некоторое значение и обертываете его с некоторой дополнительной информацией. Точно так же, как значение является определенным видом (например, целое число или строка), таким образом, дополнительной информацией является определенный вид.

    , Например, что дополнительная информация могла бы быть Maybe или IO.

  2. Тогда у Вас есть некоторые операторы, которые позволяют Вам воздействовать на обернутые данные при переносе вдоль той дополнительной информации. Эти операторы используют дополнительную информацию, чтобы решить, как изменить поведение операции на обернутом значении.

    , Например, Maybe Int может быть Just Int или Nothing. Теперь, если Вы добавите Maybe Int к Maybe Int, оператор проверит, чтобы видеть, ли они и Just Int с внутри, и если так, развернут Int с, передаст их оператор сложения, повторно обернет получающееся Int в новое Just Int (который является допустимым Maybe Int), и таким образом возвратитесь Maybe Int. Но если один из них был Nothing внутренняя часть, этот оператор просто сразу возвратится Nothing, который снова является допустимым Maybe Int. Тем путем можно притвориться, что Ваш Maybe Int с являются просто нормальными числами и выполняют регулярную математику на них. Если необходимо было добраться Nothing, уравнения все еще приведут к правильному результату †“ без Вас имеющий необходимость замусорить проверки на [1 118] везде .

, Но пример, что происходит для [1 119]. Если дополнительная информация была IO, то тот специальный оператор определил для [1 121], с назовут вместо этого, и это могло сделать что-то полностью различное прежде, чем выполнить дополнение. (Хорошо, добавляя два IO Int с вместе является, вероятно, бессмысленным †“I’m, не уверенный все же.) (Кроме того, если Вы обратили внимание на Maybe пример, Вы заметили, что “wrapping значение с дополнительным stuff” не всегда корректен. Но it’s трудно, чтобы быть точным, корректным и точным, не будучи непостижимым.)

В основном, “monad” примерно означает “pattern” . Но вместо книги, полной неофициально объясненных и специфически именованных Шаблонов, Вы теперь имеете конструкция языка †“синтаксис и весь †“, который позволяет, Вы к [1 148] объявляете новые шаблоны как вещи в Вашей программе . (Неточность вот является всеми шаблонами, должны следовать за конкретной формой, таким образом, монада не совсем так же универсальна как шаблон. Но я думаю that’s самый близкий термин, который большинство людей знает и понимает.)

И именно поэтому люди находят монады настолько сбивающими с толку: потому что они - такое универсальное понятие. Для выяснения, что делает что-то, монада столь же неопределенна для выяснения, что делает что-то шаблоном.

, Но думают о последствиях о наличии синтаксической поддержки на языке для идеи шаблона: вместо того, чтобы иметь необходимость читать Банда Четыре книга и запомнить конструкцию конкретного шаблона, Вы всего код записи, который реализует этот шаблон в агностике, универсальный путь однажды и затем Вы сделаны! Можно тогда снова использовать этот шаблон, как Посетитель или Стратегия или FaГ§ade или что бы то ни было, только путем украшения операций в коде с ним, не имея необходимость повторно реализовывать его много раз!

Так, чтобы был то, почему люди, которые понимают монады, находят их так полезными : it’s не некоторое понятие башни слоновой кости, что интеллектуальные снобы гордость себя на понимании (хорошо, это, слишком конечно, хихикают), но на самом деле делают код более простым.

44
ответ дан 4 revs, 2 users 96% 28 August 2015 в 17:05
поделиться

Монада является, эффективно, формой "оператора типа". Это сделает три вещи. Сначала это "обернет" (или иначе преобразует), значение одного типа в другой тип (обычно названный "одноместным типом"). Во-вторых, это сделает все операции (или функции) доступный на базовом типе доступный на одноместном типе. Наконец это окажет поддержку для объединения сам с другой монадой для создания составной монады.

, "возможно, монада" является по существу эквивалентом "nullable типов" в Visual Basic / C#. Это берет не nullable тип "T" и преобразовывает его в "Nullable< T>"; и затем определяет то, что все бинарные операторы означают на Nullable< T>.

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

Их называют "монадами", а не более легким к схватыванию названием "операторов типа" по нескольким причинам:

  1. Монады имеют ограничения на то, что они могут сделать (см. определение для деталей).
  2. Те ограничения, наряду с тем, что существует три включенные операции, приспосабливают структуре чего-то позвонившего монаде в Теории категорий, которая является неясным ответвлением математики.
  3. Они были разработаны сторонниками "чистых" функциональных языков
  4. Сторонники чистых функциональных языков как неясные ответвления математики
  5. , поскольку математика неясна, и монады связаны с конкретными стилями программирования, люди склонны использовать монаду слова в качестве своего рода секретного квитирования. Из-за этого никто не потрудился вкладывать капитал в лучшее имя.
33
ответ дан 5 revs, 4 users 76% 28 August 2015 в 17:05
поделиться

Мое любимое учебное руководство по Монаде:

http://www.haskell.org/haskellwiki/All_About_Monads

(из 170 000 хитов на Google ищут "учебное руководство по монаде"!)

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

у Haskell уже есть оператор, перегружающийся [1]: это использует классы типа очень способ, которым можно было бы использовать интерфейсы в Java или C#, но Haskell просто, оказывается, также позволяет неалфавитно-цифровые маркеры как + & & и> как инфиксные идентификаторы. Это - только оператор, перегружающийся в Вашем способе посмотреть на него, если Вы означаете "перегружать точку с запятой" [2]. Это походит на черную магию и напрашивающийся на неприятности для "перегрузки точки с запятой" (изображение инициативные хакеры Perl, получающие ветер этой идеи), но дело в том, что без монад нет никакой точки с запятой, так как чисто функциональный код не требует или позволяет явное упорядочивание.

это все звуки, намного более сложные, чем он, должно. статья sigfpe довольно прохладна, но использует Haskell для объяснения его, который вид сбоев повредить проблему курицы и яйца понимания Haskell к grok Монадам и пониманию Монад grok Haskell.

[1] Это - отдельный вопрос от монад, но монады используют функцию перегрузки оператора Haskell.

[2] Это - также упрощение, так как оператор для объединения в цепочку одноместных действий>> = (объявленный, "связывают"), но существует синтаксический сахар ("делают"), который позволяет Вам использовать фигурные скобки и точки с запятой и/или добавление отступа и новые строки.

14
ответ дан 2 revs 28 August 2015 в 17:05
поделиться

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

при использовании императивного языка, и Вы пишете некоторые выражения в порядке, код ВСЕГДА работает точно в том порядке.

И в простом случае при использовании монады это чувствует то же - Вы определяете список выражений, которые происходят в порядке. За исключением того, что, в зависимости от которой монады Вы используете, Ваш код мог бы работать в порядке (как в монаде IO), параллельно по нескольким объектам сразу (как в монаде Списка), это могло бы остановиться отчасти через (как в, Возможно, монаде), это могло бы приостановиться отчасти до быть возобновленным позже (как в монаде Возобновления), это могло бы перемотаться и запуститься с начала (как в монаде Транзакции), или это могло бы перемотаться отчасти для попытки других опций (как в Логической монаде).

И потому что монады являются полиморфными, возможно выполнить тот же код в различных монадах, в зависимости от Ваших потребностей.

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

9
ответ дан jes5199 28 August 2015 в 17:05
поделиться

Во-первых: термин монада немного вырождена, если Вы не математик. Альтернативный термин разработчик вычисления , который является немного более описательным из того, для чего они на самом деле полезны.

Вы просите практические примеры:

Пример 1: понимание Списка :

[x*2 | x<-[1..10], odd x]

Это выражение возвращает удваивание всех нечетных чисел в диапазоне от 1 до 10. Очень полезный!

оказывается, что это - действительно просто синтаксический сахар для некоторых операций в монаде Списка. То же понимание списка может быть записано как:

do
   x <- [1..10]
   guard (odd x)
   return (x * 2)

Или даже:

[1..10] >>= (\x -> guard (odd x) >> return (x*2))

Пример 2: ввод/вывод :

do
   putStrLn "What is your name?"
   name <- getLine
   putStrLn ("Welcome, " ++ name ++ "!")

Оба примера используют монады, иначе разработчики вычисления. Общая тема то, что монада операции цепочек некоторым определенным, полезным способом. В понимании списка операции объединяются в цепочку таким образом что, если операция возвращает список, то следующие операции выполняются на [1 135] каждый объект в списке. Монада IO, с другой стороны, выполняет операции последовательно, но проводит "скрытую переменную", которая представляет "состояние мира", который позволяет нам писать код ввода-вывода чистым функциональным способом.

Это оказывается шаблоном [1 136], операции объединения в цепочку довольно полезны и используются для большого количества разных вещей в Haskell.

Другим примером являются исключения: Используя Error монада, операции объединяются в цепочку таким образом, что они выполняются последовательно, кроме того, если ошибка брошена, в этом случае от остальной части цепочки отказываются.

И синтаксис понимания списка и-нотация являются синтаксическим сахаром для объединения в цепочку операций с помощью >>= оператор. Монада является в основном просто типом, который поддерживает >>= оператор.

Пример 3: синтаксический анализатор

Это - очень простой синтаксический анализатор, который анализирует или заключенную в кавычки строку или число:

parseExpr = parseString <|> parseNumber

parseString = do
        char '"'
        x <- many (noneOf "\"")
        char '"'
        return (StringValue x)

parseNumber = do
    num <- many1 digit
    return (NumberValue (read num))

операции char, digit, и т.д. довольно просты. Они или соответствуют или не соответствуют. Волшебство является монадой, которая управляет потоком управления: операции выполняются последовательно, пока соответствие не приводит к сбою, в этом случае отслеживание в обратном порядке монады к последнему <|> и пробует следующую опцию. Снова, способ объединить операции в цепочку с некоторой дополнительной, полезной семантикой.

Пример 4: Асинхронное программирование

вышеупомянутые примеры находятся в Haskell, но это складывается , F# также поддерживает монады. Этот пример украден от [1 132] Don Syme :

let AsyncHttp(url:string) =
    async {  let req = WebRequest.Create(url)
             let! rsp = req.GetResponseAsync()
             use stream = rsp.GetResponseStream()
             use reader = new System.IO.StreamReader(stream)
             return reader.ReadToEnd() }

Этот метод выбирает веб-страницу. Концовка является использованием [1 113] - это на самом деле ожидает ответа на отдельном потоке, в то время как основной поток возвращается из функции. Последние три строки выполняются на порожденном потоке, когда ответ был получен.

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

, Как они работают

Поэтому, как монада может сделать все, которые они представляют себе вещь потока управления? То, что на самом деле происходит в-блоке (или выражение вычисления, как их называют в F#), то, что каждая операция (в основном каждая строка) обертывается в отдельную анонимную функцию. Эти функции тогда объединены с помощью bind оператор (записал >>= в Haskell). Начиная с bind операция комбинирует функции, она может выполнить их, поскольку она считает целесообразным: последовательно, многократно, наоборот, отбросьте некоторых, выполните некоторых на отдельном потоке, когда будет похоже на него и так далее.

Как пример, это - расширенная версия IO-кода от примера 2:

putStrLn "What is your name?"
>>= (\_ -> getLine)
>>= (\name -> putStrLn ("Welcome, " ++ name ++ "!"))

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

Примечание, которое >>= перегружается для различных типов, таким образом, каждая монада имеет свою собственную реализацию [1 124]. (Все операции в цепочке должны иметь тип той же монады, хотя, иначе >>= оператор не будет работать.)

самая простая реализация [1 126] просто принимает значение слева и применяет его к функции справа и возвращает результат, но, как сказано прежде, что делает целый шаблон полезным, когда существует что-то дополнительное продолжение в реализации монады [1 127].

существует некоторый дополнительный ум в том, как значения передаются от одной операции до следующего, но это требует более глубокого объяснения системы типов Haskell.

Подведение итогов

В Haskell-терминах монада является параметризованным типом, который является экземпляром класса типа Монады, который определяет >>= наряду с несколькими другими операторами. В терминах неспециалиста монада является просто типом, для которого >>= определяется операция.

Сам по себе >>= просто громоздкий способ объединить функции в цепочку, но с присутствием-нотации, которая скрывает "инфраструктуру", одноместные операции оказывается очень хорошей и полезной абстракцией, полезной много мест на языке, и полезный для создания Ваших собственных мини-языков на языке.

, Почему монады трудно?

Для многих Haskell-учеников, монады являются препятствием, которое они поражают как кирпичная стена. It не, что сами монады сложны, но что реализация полагается на многие другие усовершенствованные функции Haskell как параметризованные типы, введите классы и так далее. Проблема состоит в том, что ввод-вывод Haskell основан на монадах, и ввод-вывод является, вероятно, одной из первых вещей, которые Вы хотите понять при изучении нового языка - в конце концов, это не много забавы создать программы, которые не производят вывода. У меня нет непосредственного решения для этой проблемы курицы-и-яйца, кроме обработки ввода-вывода как "волшебство происходит здесь", пока у Вас нет достаточного опыта с другими частями языка. Извините.

Превосходный блог на монадах: http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html

1020
ответ дан 17 revs, 13 users 71% 28 August 2015 в 17:05
поделиться

В дополнение к превосходным ответам выше, позвольте мне предложить Вам ссылку на следующую статью (Patrick Thomson), который объясняет монады путем связи понятия с библиотекой JavaScript jQuery (и его способ использовать "объединение в цепочку метода" для управления DOM): jQuery является Монада

, документация jQuery сама не относится к термину "монада", но говорит о "шаблоне разработчика", который, вероятно, более знаком. Это не изменяет то, что у Вас есть надлежащая монада там, возможно, даже не понимая его.

8
ответ дан siggboy 28 August 2015 в 17:05
поделиться

Монады предназначены для управления потоком, какие абстрактные типы данных относятся к данным.

Другими словами, многим разработчикам нравится идея наборов, списков, словарей (или хэшей, или карт) , и деревья. В этих типах данных есть много особых случаев (например, InsertionOrderPreservingIdentityHashMap).

Однако, столкнувшись с «потоком» программы, многие разработчики не сталкивались с большим количеством конструкций, чем if, switch / case, do, while, goto (grr) и (возможно) замыкания.

Итак, монада - это просто конструкция потока управления. Лучшей фразой для замены монады было бы «тип управления».

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

Например, монада «if»:

if( clause ) then block

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

Монады могут стать более сложными, так же как и структуры данных, но есть много широких категорий монад, которые могут иметь схожую семантику, но разные реализации и синтаксис.

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

Компиляторы может иметь или не поддерживать определяемые пользователем монады. Haskell определенно знает. Иоке имеет аналогичные возможности,

23
ответ дан 19 December 2019 в 20:15
поделиться

Мне больше всего помогли две вещи:

Глава 8, «Функциональные синтаксические анализаторы», из книги Грэма Хаттона Программирование на Haskell . На самом деле здесь вообще не упоминаются монады, но если вы можете проработать главу и действительно понять все в ней, особенно то, как оценивается последовательность операций связывания, вы поймете внутреннее устройство монад. Ожидайте, что для этого потребуется несколько попыток.

Учебник Все о монадах . Это дает несколько хороших примеров их использования, и я должен сказать, что аналогия в Appendex, которую я использовал для меня.

5
ответ дан 19 December 2019 в 20:15
поделиться

http://code.google.com/p/monad-tutorial/ - работа над решением именно этого вопроса продолжается.

4
ответ дан 19 December 2019 в 20:15
поделиться

Монада - это способ объединения вычислений в общем контексте. Это похоже на строительство сети труб. При построении сети данные не проходят через нее. Но когда я закончил собирать все биты вместе с помощью 'bind' и 'return', я вызываю что-то вроде данных монады runMyMonad , и данные проходят по каналам.

7
ответ дан 19 December 2019 в 20:15
поделиться

Объяснение Princess F # Computing Expressions помогло мне, хотя я все еще не могу сказать, что действительно понял.

EDIT : эта серия - объяснение монад с помощью javascript - для меня "склонила чашу весов".

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

Некоторые вещи, которые мне было трудно понять:

2
ответ дан 19 December 2019 в 20:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: