Haskell язык ленивый. Для интерактивных программ достаточно вообще обычных строк:
main = interact realMain
realMain :: String -> String
realMain = unlines . f . lines
  where
    f x = "Введите своё имя: ":g x
    g (имя:числа) = ["Привет, " ++ имя, "Вводите числа, q для выхода"] ++ корни числа
    корни ("q":_) = []
    корни (x:xs) = (show . sqrt) (read x :: Double):корни xs
Вот программа, которая запрашивает имя пользователя, затем выводит корни введённых чисел пока не получит q. Никакого IO внутри realMain не требуется.
Если брать произвольное взаимодействие с окружающим миром, то достаточно main :: [inEvent] -> [outEvent].
Зачем нужен «магический» тип IO, делящий Haskell на фактически два разных языка?




