Несколько проблем:
- Невозможно написать функцию, которая берет
IO
чего-либо и использует ее для возврата чего-то, чего нет в IO
. Измените showBoard
на Array Int Char
без оболочки IO
и удалите из него do
и return
.
- Поскольку ваш массив начинается с нуля, измените
arr ! i
на arr ! (i - 1)
.
arr
содержит Char
с, а не String
с, поэтому используйте []
вместо ()
вокруг индексации, чтобы превратить его в String
.
- Поскольку мы заставили
showBoard
принять значение без IO
, используйте <-
в main
, чтобы получить необходимое нам внутреннее значение.
Вот результат всех этих изменений:
import System.Random
import Control.Monad
import Data.Array
import Data.List
randomBoard = do
f1 <- randomIO :: IO Int
if(f1 `mod` 2) == 0
then return '*'
else return ' '
boardArray :: IO (Array Int Char)
boardArray = listArray (0, 99) <$> replicateM 100 randomBoard
showBoard :: Array Int Char -> Int -> String -> String
showBoard arr i str =
if i > 0
then showBoard arr (i-1) (str ++ [arr ! (i - 1)])
else str
main :: IO ()
main = do
randomArray <- boardArray
let board = showBoard randomArray 100 ""
putStr board
Кроме того, способ реализации showBoard
, хотя и работает, особенно неэффективен. Вы должны избегать рекурсивных действий, которые выглядят как x ++ [y]
, поскольку это квадратично медленно. Кроме того, похоже, что ваша функция печатает элементы, начиная с конца и опускаясь до 0, а не начиная с 0 и доходя до конца. Вот новая версия, которая исправляет обе эти вещи сразу:
showBoard :: Array Int Char -> Int -> String -> String
showBoard arr i str =
if i > 0
then showBoard arr (i-1) ((arr ! (i - 1)) : str)
else str
Использование :
, где это возможно, намного эффективнее, чем всегда использование ++
.
Вы можете упростить еще больше, не имея вообще showBoard
, и вместо этого используйте elems
(из Data.Array
):
main :: IO ()
main = do
randomArray <- boardArray
let board = elems randomArray
putStr board