I'm trying to do a flocking simulation in order to better teach myself haskell. I'm running into trouble when trying to generate the initial state for the simulation which requires randomness. I'm trying to generate a list of Boids which all have random initial positions and directions.
In the main function I call this using
let numBoids = 10
rBoids <- randomBoids numBoids
And rBoids
I indend to store in an IORef which I can then update every frame, which I think is the right way to do things?
And here is the code which fails:
-- Type for the flocking algorithm
data Boid = Boid {
boidPosition :: Vector2(GLfloat)
, boidDirection :: Vector2(GLfloat)
} deriving Show
randomBoids :: Int -> IO ([Boid])
randomBoids 0 = do
return []
randomBoids n = do
b <- randomBoid
bs <- (randomBoids (n-1))
return b : bs
randomBoid = do
pos <- randomVector
vel <- randomVector
return (Boid pos vel)
randomVector = do
x <- randomRIO(-1.0, 1.0)
y <- randomRIO(-1.0, 1.0)
return (Vector2 x y)
What actually fails is return b : bs
. If I change this into return [b]
it compiles. The error given is:
Couldn't match expected type `IO [Boid]' with actual type `[a0]'
In the expression: return b : bs
In the expression:
do { b <- randomBoid;
bs <- (randomBoids (n - 1));
return b : bs }
In an equation for `randomBoids':
randomBoids n
= do { b <- randomBoid;
bs <- (randomBoids (n - 1));
return b : bs }
I'm pretty lost here, and my understanding of the whole imperative-code-in-a-functional language (and monads) is shaky to say the least. Any help would be most appreciated!
Gangadahr is correct. I only wanted to mention that you can shorten your code a LOT:
import Control.Applicative
import Control.Monad
randomBoids n = replicateM n randomBoid
randomBoid = Boid <$> randomVector <*> randomVector
randomVector = Vector2 <$> randomRIO (-1, 1) <*> randomRIO (-1, 1)
The first function takes advantage of replicateM
, which is a very useful function when you want to repeat a monadic action and collect the results. The latter two functions use Applicative
style, which is enormously useful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With