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