Vous devez séparer deux problèmes ici. D'abord, vous devez calculer la valeur du pixel. Il doit s'agir d'une fonction pure de la scène et de la coordonnée du rayon que vous envoyez dans la scène. Ensuite, vous devez écrire cette valeur de pixel à l'écran.
Donc d'abord vous voulez une fonction :
type Coord = (Int, Int)
raytrace :: Scene -> Coord -> (Coord, Colour)
-- You will see why it returns this pair in a few lines
Vous voulez ensuite appeler cette fonction pour chaque pixel de votre surface, afin d'obtenir une liste de paires coordonnées-couleurs :
allCoords :: Int -> Int -> [Coord]
allCoords width height = [(x,y) | x <- [0..width], y <- [0..height]]
allPixels :: Scene -> Int -> Int -> [(Coord, Colour)]
allPixels scene w h = map (raytrace scene) (allCoords w h)
Et enfin, mettez la liste des pixels sur la surface d'affichage en utilisant votre fonction "pixel".
writeScene :: Surface -> Scene -> Int -> Int -> IO ()
writeScene surface scene w h = mapM_ writePixel (allPixels scene w h)
where writePixel ((x,y),c) = pixel surface x y c
Le seul problème est que votre fonction "pixel" renvoie un "IO Bool". Je ne sais pas pourquoi, alors je l'ai ignoré en utilisant "mapM_" plutôt que "mapM".
On a l'impression qu'il s'agit de construire une liste terriblement inefficace de paires coordonnées-couleurs, puis de la parcourir pour dessiner l'image. Mais en fait, grâce à la nature paresseuse de Haskell, elle se compile en une boucle qui génère chaque couleur et appelle ensuite "pixel" sur le résultat.