Reputation: 85
I am trying to make Conway's Game of Life in Haskell. I am very new to Haskell and functional programming in general, and having trouble making an array in haskell to represent the game board.
I am trying to initiate a random array to begin the game. To do that I create a function randomBoard which returns '*' or ' ' to represent a space on the game board.
I want to be able to create the game board array with this function. I havent been able to succesfully instantiate an array yet. I am hoping there is a way i can declare an array of say size 100 and use my random function to set each element.
import System.Random
import Data.Array
import Data.List
randomBoard =
do
f1 <- randomIO :: IO Int
if(f1 `mod` 2) == 0
then return '*'
else return ' '
boardArray :: Array Int Char
boardArray = listArray (0, 100) . map randomBoard $ 100 (0,100)
This obviously doesnt work or even compile. I am sure there are a couple things wrong with it, as I am not sure really how to even work with IO in haskell and produce this outcome. Any guidance is much appreciated...
Upvotes: 1
Views: 1435
Reputation: 48672
This should work for you:
import Control.Monad
import System.Random
import Data.Array
import Data.List
randomBoard :: IO Char
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
Here's what I changed:
randomBoard :: IO Char
for clarity. (The code would still work without it, as Haskell correctly infers this type if you don't supply it.)boardArray
to use IO
. Anything that uses IO
, no matter how indirectly, need to be in IO
itself.listArray (0, 100)
to listArray (0, 99)
, as the former would actually be 101 elements.map randomBoard $ 100 (0,100)
isn't right at all. To get a list of several of the same thing, you'd usually use replicate
, but since the thing you care about here is in the IO
monad, you use replicateM
instead. replicateM 100 randomBoard
gives an IO [Char]
with 100 random elements of either '*'
or ' '
.Control.Monad
, which is needed to use replicateM
.<$>
in boardArray
. Since you want to call listArray
with a [Char]
and get an Array Int Char
, but replicateM 100 randomBoard
is an IO [Char]
, you can't just apply the argument directly. Using <$>
(which is also called fmap
) applies it "inside" of IO
, giving you back an IO (Array Int Char)
.Upvotes: 7