Я пытаюсь заставить рекурсию работать бесконечно для моего проекта. Это мой код:
putStr' :: String -> IO ()
putStr' (a:as) = do putChar a
putChar '\n'
threadDelay 1000000
putStr' as
putStr' [] = putStr'
выдает эту ошибку
<interactive>:339:18: error:
* Couldn't match expected type: IO ()
with actual type: String -> IO ()
* Probable cause: putStr' is applied to too few arguments
In the expression: putStr'
In an equation for putStr': putStr' [] = putStr'
Я тоже это попробовал
putStr' :: String -> IO ()
putStr' (a:as) = do putChar a
putChar '\n'
threadDelay 1000000
putStr' as
putStr' [] = putStr' (a:as)
но безрезультатно, как он мне говорит:
<interactive>:297:27: error: Variable not in scope: a :: Char
<interactive>:297:29: error: Variable not in scope: as :: [Char]
Я знаю, что вы не должны этого делать, поскольку это может быть опасно, но на самом деле это то, что мне нужно, чтобы мой код работал. Можете ли вы мне помочь? Возможно ли это вообще? Стоит ли мне попробовать другой подход, возможно, использовать охрану или что-то еще?
«Я знаю, что вам не следует этого делать, поскольку это может быть опасно, но на самом деле это то, что мне нужно, чтобы мой код работал». – Пожалуйста, не описывайте попытку решения, а опишите реальную проблему, чтобы избежать проблемы XY.
Не думайте о вечном цикле; подумайте о цикле по списку, который может быть или не быть бесконечным, а затем предоставить бесконечный список.
putStr' :: String -> IO ()
putStr' = traverse_ go . cycle where
go x = do putChar x
putChar '\n'
threadDelay 1000000
Скучное базовое решение — добавить второй аргумент, который никогда не меняется, чтобы мы могли «сбросить» первый аргумент по мере необходимости.
putStr'2 :: String -> String -> IO ()
putStr'2 (a:as) bs = do putChar a
putChar '\n'
threadDelay 1000000
putStr'2 as bs
putStr'2 [] bs = putStr'2 bs bs
putStr' :: String -> IO ()
putStr' as = putStr'2 as as
Это далеко не элегантно, но для понимания не требуется сложных концепций.
Использование внутреннего определения также является относительно простым.
putStr' :: String -> IO ()
putStr' bs = putStr'2 bs
where
putStr'2 :: String -> IO ()
putStr'2 (a:as) = do putChar a
putChar '\n'
threadDelay 1000000
putStr'2 as
putStr'2 [] = putStr'2 bs
Установите
putStr' [] = pure ()
, а затем используйтеforever (putStr' s)
.