Ниже приведен ужасный пример. Вы были предупреждены.
Рассмотрим псевдокод:
var x = 23
while (x != 0) {
print "x not yet 0, enter an adjustment"
x = x + read()
}
print "x reached 0! Exiting"
Вот его пошаговый перевод на Haskell, максимально используя императивный стиль.
import Data.IORef
main :: IO ()
main = do
x <- newIORef (23 :: Int)
let loop = do
v <- readIORef x
if v == 0
then return ()
else do
putStrLn "x not yet 0, enter an adjustment"
a <- readLn
writeIORef x (v+a)
loop
loop
putStrLn "x reached 0! Exiting"
Это действительно ужасный Haskell. Он имитирует цикл while, используя рекурсивно определенный loop
, что не так уж плохо. Но он везде использует ввод-вывод, в том числе для имитации изменяемых переменных в императивном стиле.
Лучшим подходом может быть удаление этих IORef
.
main = do
let loop 0 = return ()
loop v = do
putStrLn "x not yet 0, enter an adjustment"
a <- readLn
loop (v+a)
loop 23
putStrLn "x reached 0! Exiting"
Не элегантный код с любой натяжкой, но, по крайней мере, «защита в то время» теперь не делает ненужного ввода-вывода.
Обычно программисты на Haskell изо всех сил стараются отделить чистые вычисления от операций ввода-вывода, насколько это возможно. Это потому, что это часто приводит к лучшему, более простому и менее подверженному ошибкам коду.
person
chi
schedule
13.02.2017