Это монадное ограничение является эвристическим трюком. Это помогает дисциплинированным пользователям избежать вложенного параллелизма, но ничего не делает против злонамеренных или невежественных пользователей.
Вложенный параллелизм — это ситуация, когда при параллельном вычислении некоторого массива вам приходится параллельно вычислять другой массив. Repa его не поддерживает (причина не важна), поэтому старается его избегать.
Тип computeP
помогает гарантировать, что параллельные вычисления выполняются последовательно друг с другом, но он далеко не герметичен; это всего лишь абстракция "наилучшего усилия".
Как монада обеспечивает это?
На самом деле ожидается, что computeP
будет работать только с монадами, чье связывание (>>=)
является строгим в своем первом аргументе, так что в u >>= k
функция k
будет применена только после того, как u
будет вычислено. Тогда, если вы используете computeP
с такой монадой,
do w <- computeP v
k w
гарантируется, что вектор w
оценивается до того, как он будет передан в k
, который может безопасно выполнять другие computeP
операции.
- Примеры строгих монад:
IO
, строгие State
, Maybe
, []
.
- Примеры ленивых монад:
Identity
, ленивые State
, Reader
. (Ленивые монады можно сделать строгими, но не наоборот. В частности, вы можете определить строгую идентификационную монаду, если хотите выполнять только вычисления Repa.)
Чтобы предотвратить вложенный параллелизм, тип computeP
намеренно делает его громоздким для использования в операциях, которые, вероятно, будут выполняться параллельно, таких как map :: (a -> b) -> Array _ _ a -> Array _ _ b
и fromFunction :: sh -> (sh -> a) -> Array _ _ a
, которые принимают немонадические функции. Можно еще явно развернуть computeP
, например, с runIdentity
, как вы заметили: вы можете выстрелить себе в ногу, если хотите, но вы должны зарядить пистолет, направить его вниз и нажать на спусковой крючок.
Надеюсь, это отвечает на вопрос, что происходит в Repa. Далее следует теоретическое отступление, чтобы ответить на этот другой вопрос:
Что именно означает наличие этого «последовательного свойства»?
Эти цитаты довольно неуклюжи. На мой взгляд, отношение между «последовательностью» и «монадами» двоякое.
Во-первых, для многих монад в Haskell определение (>>=)
естественным образом диктует порядок вычисления, обычно потому, что оно сразу же соответствует шаблону в первом аргументе. Как объяснялось ранее, это то, на что Repa полагается, чтобы обеспечить последовательное выполнение computeP
вычислений (и именно поэтому он сломается, если вы настроите его на Identity
; это не строгая монада). По большому счету, это довольно незначительная деталь ленивых вычислений, а не что-либо, свойственное монадам в целом.
Во-вторых, одной из основных идей чисто функционального программирования являются первоклассные вычисления с явным определением эффектов и композиции. В этом случае эффектом является параллельная оценка векторов, а интересующая нас композиция — это последовательная композиция. Монады обеспечивают общую модель или интерфейс для последовательной композиции. Это еще одна причина, по которой монады помогают решить проблему предотвращения вложенного параллелизма в Repa.
Дело не в том, что монады по своей природе имеют последовательный аспект, а в том, что последовательная композиция по своей сути монадична: если вы попытаетесь перечислить общие свойства, которые вы ожидаете от чего-либо, достойного названия «последовательная композиция», вы, скорее всего, закончите. со свойствами, которые вместе называются «монадой»; это один из пунктов основополагающей статьи Моджи «Понятия вычислений и монад».
«Монады» — это не волшебное понятие, а чрезвычайно общее понятие, так что многие вещи оказываются монадами. Ведь главное требование — наличие ассоциативной операции; это довольно разумное предположение о последовательной композиции. (Если, когда вы слышите «ассоциативность», вы думаете «моноид» или «категория», обратите внимание, что все эти понятия объединены под эгидой «моноидальных объектов», так что, что касается «ассоциативности», они все та же идея, только в разных категориях.)
person
Li-yao Xia
schedule
05.01.2020
What does having this 'sequential property' mean
иwhy does computeP pack its result in a monad
. Последнее на самом деле подразумевается как пример первого: я предполагаю, что calculateP использует монаду из-за этого свойства последовательности, но я хотел бы получить некоторые разъяснения о том, как именно работает это свойство последовательности. Это то, что ты имеешь в виду? Если вы можете уточнить, я был бы более чем готов уточнить вопрос или разделить его на несколько вопросов. - person Safron   schedule 04.01.2020