功能相当于迭代2D数组

时间:2011-02-11 04:30:40

标签: haskell functional-programming

我在Haskell中有这个功能(我正在使用Haskell-SDL库):

pixel :: Surface -> Int16 -> Int16 -> Pixel -> IO Bool

pixel screen x y color

我想使用它来获取2D数组(或其他类型的数据结构)并将其绘制到屏幕上,一次一个像素。我调查了forM_,但无法弄清楚如何让它对x和y参数进行操作。

我对Haskell和一般的函数式编程都很陌生。我正在通过Yet Another Haskell Tutorial工作,但这个问题让我感到难过。

如果它与解决方案相关,我正在尝试编写光线跟踪器。它必须对每个像素执行计算,然后将该像素写入屏幕。

3 个答案:

答案 0 :(得分:3)

如果您使用的是嵌套列表,请执行以下操作:

import Control.Monad
plot :: Surface -> [[Pixel]] -> IO ()
plot surf = zipWithM_ (\ y -> zipWithM_ (\ x c -> pixel surf x y c) [0..]) [0..]

答案 1 :(得分:2)

Haskell有各种各样的真实数组。对我来说,你似乎在做一些非常低效的事情,你想创建一个像素缓冲区并将其blit到另一个缓冲区?创建一个新的SDL表面(你可以获得/设置像素)并将其blit到另一个表面/屏幕或创建一个真实的像素阵列并创建SDL表面然后使用SDL的blit例程会更有效。如果你解释一下你想要做什么,我想我们可以向你展示更好的方法。

答案 2 :(得分:0)

你需要在这里分解两个问题。首先,您需要计算像素值。这应该是场景的纯函数以及射入其中的光线的坐标。然后你需要将该像素值写入屏幕。

首先你想要一个功能:

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)

最后使用“像素”功能将像素列表放在显示表面上。

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

唯一的问题是,你的“像素”函数会返回“IO Bool”。我不知道为什么,所以我通过使用“mapM_”而不是“mapM”来忽略它。

这看起来它构建了一个非常低效的坐标颜色对列表,然后迭代它来绘制图片。但事实上,由于Haskell的惰性,它实际上编译成一个循环,生成每种颜色,然后在结果上调用“像素”。