Anon.
Anon.

Reputation: 85

Mapping function to list/array in haskell?

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

Answers (1)

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:

  1. I added the type signature randomBoard :: IO Char for clarity. (The code would still work without it, as Haskell correctly infers this type if you don't supply it.)
  2. I changed the type of boardArray to use IO. Anything that uses IO, no matter how indirectly, need to be in IO itself.
  3. I changed listArray (0, 100) to listArray (0, 99), as the former would actually be 101 elements.
  4. 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 ' '.
  5. I added an import of Control.Monad, which is needed to use replicateM.
  6. I use <$> 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

Related Questions