Вам нужно разделить две проблемы здесь.Сначала вам нужно вычислить значение пикселя.Это должно быть чистой функцией сцены и координаты луча, в который вы в нее стреляете.Затем вам нужно записать значение этого пикселя на экран.
Итак, сначала вам нужна функция:
type Coord = (Int, Int)
raytrace :: Scene -> Coord -> (Coord, Colour)
-- You will see why it returns this pair in a few lines
Затем вы хотите вызвать эту функцию для каждого пикселя на вашей поверхности, чтобы получитьсписок пар координат и цветов:
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)
И, наконец, поместите список пикселей на поверхность дисплея с помощью функции «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
Единственное, чтоФункция «pixel» возвращает «IO Bool».Я не знаю почему, поэтому я проигнорировал это, используя «mapM_», а не «mapM».
Похоже, что он создает ужасно неэффективный список пар координат-цвет и затем перебирает егонарисовать картину.Но на самом деле, благодаря ленивой природе Haskell, он фактически компилируется в цикл, который генерирует каждый цвет, а затем вызывает «пиксель» в результате.