вот некоторая пища для размышлений.
Когда я пишу монадический код, монада упорядочивает выполняемые операции. Например, если я напишу в монаде IO:
do a <- doSomething
b <- doSomethingElse
return (a + b)
Я знаю, что doSomething
будет казнен раньше doSomethingElse
.
Теперь рассмотрим эквивалентный код на таком языке, как C:
return (doSomething() + doSomethingElse());
Семантика C на самом деле не указывает, в каком порядке будут оцениваться вызовы этих двух функций, поэтому компилятор может перемещать вещи по своему усмотрению.
Мой вопрос заключается в следующем: Как мне написать монадический код на Haskell, который также оставляет этот порядок вычисления неопределенным? В идеале я бы получил некоторые преимущества, когда оптимизатор моего компилятора просматривает код и начинает перемещать вещи.
Вот несколько возможных методов, которые не выполняют свою работу, но находятся в правильном «духе»:
- Напишите код в функциональном стиле, то есть напишите
plus doSomething doSomethingElse
и позвольтеplus
планировать монадические вызовы. Недостатки: вы теряете совместное использование результатов монадических действий, иplus
по-прежнему принимает решение о том, когда вещи в конечном итоге будут оценены. - Используйте отложенный ввод-вывод, то есть
unsafeInterleaveIO
, который откладывает планирование до требований отложенной оценки. Но lazy отличается от strict неопределенным порядком: в частности, я хочу, чтобы все мои монадические действия выполнялись. - Ленивый ввод-вывод в сочетании с немедленной последовательностью всех аргументов. В частности,
seq
не накладывает ограничений на порядок.
В этом смысле я хочу чего-то более гибкого, чем монадический порядок, но менее гибкого, чем полная лень.
unordered :: (IO a) -> (IO b) -> IO (a, b)
с семантикой, что порядок побочных эффектов не определен. Похоже, вам нужен какой-то примитив, чтобы сделать это без накладных расходовforkIO
. - person hammar   schedule 05.05.2011