Разъясню для тех кто хаскелл в глаза не видел как оно там устроено (надеюсь знающие меня поправят, наверняка я где-то ошибусь):
В хаскеле по умолчанию нет побочных эффектов. Т.e. совсем нет. Все не изменно и так далее. Однако, очевидно что так жить нельзя :-) Поэтому в стандартной библиотеке есть множество функций позволяющих создавать изменяемые значения и менять их, лазить по памяти и что-то там ещё. Соответственно правило – из такой функции можно вызвать чистую функцию, из чистой функции вызвать такую функцию нельзя.
Теперь о том, как это правило реализуется: в хаскеле система типов, грубо говоря позволяет вешать тип на тип. То есть например функция у нас возвращает тип "A", мы можем написать функцию которая будет возвращать тип "B A". Причем если конструкторы типа B не экспортируются в модуле где определен B, то у тебя нет никакой возможности из значения типа "B A" получить нечто типа "A". При этом модуль где вводится тип B может иметь функцию преобразующая значение любого типа A (C,D,E… без разницы), в значение типа "B A".
Тип функций через которые возможны побочные эффекты имеют тип IO, конструкторы этого типа программисту не доступны. В хаскеле нет по сути statement'ов, соответственно там есть только выражения. Т.e. вызвать функцию с побочным эффектом и проигнорировать её тип не выйдет, её тип будет влиять на тип функции её вызвавшую. (всем очевидно, что в выражении a+b+c+d*z – типы переменных влияют на результат). Соответственно функция вызвавшая функцию с типом "IO что-то-там" также становится функцией типа "IO что-то-там' ".
Вот и всё. И никакой черной магии и поддержки со стороны компилятора конкретно этого. Просто система типов + отсутствие побочных эффектов в ЯЗЫКЕ (они в стандартной либе). Ну а автоматический вывод типов делает все это юзабельным (иначе потонули бы в ручной декларации типов). А монадный синтаксис делает это еще и читабельным.
Механизм общий, через него можно очень многое делать. Собственно управление побочными эффектами (IO) лишь малая толика того, что делают посредством этой системы типов.