Вы запрашиваете способ обновления некоторого (возможно, скрытого) состояния при каждом вызове процедуры, чтобы функция возвращала разные результаты при одном и том же вводе.
Очевидно, что это не относительная прозрачность функции, поэтому мы должны добавить что-то в режим чисто по умолчанию в Haskell. Мы добавляем понятия вычисления с помощью монад. Вам просто нужно выбрать нужную вам монадическую среду.
Государственная монада
Самый точный способ - это просто добавить в вашу программу понятие состояния через монаду состояний (не путать с монадой "ST"):
import Control.Monad.State.Strict
-- a (stateful) procedure, that returns and increments an internal state counter
f :: State Int Int
f = do
n <- get
put (n+1)
return n
-- Call 'f' a bunch of times, print the final state.
main = print $ execState code 0
where
code = do f; f; f; f
Теперь у 'f' есть внутренний компонент состояния.
Аналогично, в более богатых средах, таких как IO, допускается State, поэтому вы можете использовать монаду IO (или другую вычислительную среду с подчиненным состоянием).