Так же, как пояснение: для приложения, подобного тому, которое вы, похоже, создаете, создание IORef с использованием unsafePerformIO
вполне нормально и допускает наиболее близкое приближение Haskell к глобальным переменным в процедурных языках.То, что, вероятно, не разумно, использует это в своих действиях.Например, newNode, вероятно, лучше всего записать как:
newNode = do i <- readIORef counter
writeIORef counter (i+1)
return i
И тогда любое место, которое вы намереваетесь вызвать newNode
, должно быть само действием ввода-вывода.
Еще одна маленькая деталь: counter
будет иметь тип IORef Integer
по умолчанию, если вы не измените его с помощью default
.Не пытайтесь дать ему общий тип, такой как Num a => IORef a
: в этом заключается опасность.