Functional equivalent to iterating over a 2D array - haskell

I have this function in Haskell (I am using the Haskell-SDL library):
pixel :: Surface -> Int16 -> Int16 -> Pixel -> IO Bool
pixel screen x y color
I want to use this to take a 2D array (or some other kind of data structure) and draw it to the screen, one pixel at a time. I looked into doing it with forM_ but can't figure out how to get it to operate on the x and y arguments.
I'm pretty new to Haskell and functional programming in general. I'm working my way through Yet Another Haskell Tutorial but this problem just has me stumped.
In case it's relevant to the solution, I'm trying to write a raytracer. It has to perform a calculation for each pixel, then write that pixel to the screen.

If you are using nested lists, do:
import Control.Monad
plot :: Surface -> [[Pixel]] -> IO ()
plot surf = zipWithM_ (\ y -> zipWithM_ (\ x c -> pixel surf x y c) [0..]) [0..]

You need to split two problems here. First you need to compute the pixel value. This should be a pure function of the scene and the coordinate of the ray you are firing into it. Then you need to write that pixel value to the screen.
So first you want a function:
type Coord = (Int, Int)
raytrace :: Scene -> Coord -> (Coord, Colour)
-- You will see why it returns this pair in a few lines
Then you want to call that function for every pixel in your surface, to get a list of coordinate-colour pairs:
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)
And finally put the list of pixels onto the display surface using your "pixel" function.
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
The only thing is, your "pixel" function returns an "IO Bool". I don't know why, so I've ignored it by using "mapM_" rather than "mapM".
This looks like it builds a horribly inefficient list of coordinate-colour pairs and then iterates through it to draw the picture. But in fact, thanks to the lazy nature of Haskell, it actually compiles down to a loop that generates each colour and then calls "pixel" on the result.

Haskell has real arrays of various kinds. To me it seems like you're doing something quite inefficient, you want to create a pixel buffer and blit it to another buffer? it would be much more efficient to create a new SDL surface (for which you can get/set pixels) and blit that to another surface/screen or create a real array of pixels and create SDL surface with that then use SDL's blit routines. If you explain what you're trying to do I think we can show you a better way.

Related

Implementing minimax by recursively folding

I'm writing a checkers AI for a standard 8*8 drafts version of the game.
The state is represented as a lens with lists of Coords representing the pieces on the board. What I am trying to do is follow this pseudo code for a Min-Max search.
function minimax(position, depth, maximizingPlayer)
if depth == 0 or game over in position
return static evaluation of position
if maximizingPlayer
maxEval = -infinity
for each child of position
eval = minimax(child, depth-1, False)
maxEval = max(maxEval, eval)
return maxEval
else
minEval = +infinity
for each child of position
eval = minimax(child, depth-1, true)
minEval = min(minEval, eval)
return minEval
By my understanding, in my case, position would be the GameState. So in my program, I would want to call minimax again on all children of the GameState, which would each just be a GameState with a move applied to it. Eventually I would hit depth 0 in which I would return a heuristic I have made a function to calculate. Where I am stuck is how to iterate through each possible GameState after a move. I have a function that calculates all possible moves that can be made from a specific GameState, but I'm stuck on how to iterate through all those moves, calling minimax with the new GameState resulting from the application of every one of the moves.
Going back to the pseudocode, I know that child will be a function call applyMove which takes in a Move and the current GameState, and returns a GameState with the new placement of pieces. Each "child" will be a different GameState resulting from different moves. I'm pretty new to Haskell and I know I'll probably need to use a fold for this. But I'm just stuck on how to write it, and I can't find many examples that I can easily relate to my situation. Any advice/tips are greatly appreciated.
The moves list would look something like this: [[(1,2),(2,3)],[(3,6),(2,7)]] and the child of a GameState would be a GameState after the application of a move, e.g
applyMove [(1,2),(2,3)] gameState.
You have a few functions already:
legalMoves :: Position -> [Move]
applyMove :: Position -> Move -> Position
I think your minimax would be cleaner with a different signature: instead of taking a Bool to decide whether to maximize or minimize, with different cases for each, it's simpler to always try to maximize, and vary the evaluation function instead, by flipping its sign at each step.
Once you have that, you don't really need to write a fold manually: just map recursive calls over each legal move, and glue them together with maximum to find the best move for the current player.
minimax :: (Position -> Int) -> Int -> Position -> Int
minimax eval 0 pos = eval pos
minimax eval n pos = case legalMoves pos of
[] -> eval pos
moves -> maximum . map negate
. map (minimax (negate . eval) (n - 1) . applyMove pos)
$ moves
Note that your specification makes it impossible to decide what move is the best, only what score you could get by making the best move. To find the best move, you'll want to make minimax return a tuple containing both the score and the move made to get there, or something of that sort.

Single Type With Several Data Constructors vs. Several Types

Consider the following type which describes the structure of some 2-dimensional shapes:
data DrawingElem
= Rect Pos Size
| Circle Pos Radius
| Ellipse Pos Radius Radius
| Line Pos Pos
| Polygon [Pos]
| Polyline [Pos]
| Group [DrawingElem]
| Drawing [DrawingElem]
which make use of these definitions:
data Vec = Vec Double Double
type Pos = Vec
type Size = Vec
type Radius = Double
The last two data constructors of DrawingElem are somehow special, because they make tree-like arrangements of the other types possible.
mydrawing = Drawing [Rect (Vec 0 0) (Vec 10 10),
Group (Vec 30 40) [Circle (Vec 0 0) 90,
Line (Vec 0 0) (Vec 50 50)]]
Such a data structure should finally being transformed into a renderable SVG-String:
toSvg :: DrawingElem -> String
toSvg (Drawing xs) = "<svg>" ++ concatMap toSvg xs ++ "</svg>"
toSvg (Group xs) = "<g>" ++ concatMap toSvg xs ++ "</g>"
toSvg (Rect (Vec x y) (Vec w h)) = "<rect x='" ++ x ... "</rect>"
For this purpose, it looks to me it was necessary to wrap the different shapes inside the DrawingElem type. They must have the same type in order to be nested and finally rendered.
In some other occasions, I'd like them being different types however: Say for a function which sets the size of a rectangle (and this only makes sense for rectangles, the others don't have the notion of a size):
setSize :: Size -> Rect -> Rect
This of course does not work with the above definitions and must be:
setSize :: Size -> DrawingElem -> DrawingElem
setSize (Rect p s) = ..
setSize x = x
So I'd have to implement a wildcard that makes the function complete. However writing setSize someSize someCircle without getting a type error looks problematic to me.
So finally I'm struggling with wrapping the drawing Elements inside a type VS. letting them being different types. Both properties are needed in different situations as described above.
Does someone have an advice for this? Is is an either-or, or is there maybe a way to model it which takes advantage of both ways?
One option is to use another indirection layer, and have a precise type for each element:
data DrawingElem
= DERect Rect
| DECircle Circle
...
data Rect = Rect Pos Size
data Circle = Circle Pos Radius
toSvg :: DrawingElem -> String
...
setSize :: Size -> Rect -> Rect
...
As a minor downside here we need to pattern match both layers, e.g.
toSvg (DERect (Rect pos size)) = ...
A more advanced alternative could be using a GADT. This might be overkill for your task, though.
{-# LANGUAGE GADTs, DataKinds #-}
data ElemType = Rect | Circle | ...
data DrawingElem (t :: ElemType) where
DERect :: Pos -> Size -> DrawingElem Rect
DECircle :: Pos -> Radius -> DrawingElem Circle
...
-- this works on all element types t
toSvg :: DrawingElem t -> String
...
-- this works only on a rectangle element
setSize :: Size -> DrawingElem Rect -> DrawingElem Rect
setSize size (DERect pos _) = DERect pos size
I am unconvinced about whether you actually need this. If in doubt, stick with the simpler alternative.
However writing setSize someSize someCircle without getting a type error looks problematic to me.
That would be problematic indeed. To avoid that, I will suggest a third option: perhaps you don't actually need a rectangle-specific setSize function at all. An alternative approach would be keeping a single DrawingElem type, setting an initial size on rectangle construction (and the initial radius on circle construction, etc.) and using functions that can be implemented for all kinds of elements to adjust the size after construction, such as:
scale :: Double -> DrawingElem -> DrawingElem
scaleX :: Double -> DrawingElem -> DrawingElem
scaleY :: Double -> DrawingElem -> DrawingElem
That is very similar to how gloss handles shapes (cf. the relevant type definition and some picture manipulation functions). Another example worth mentioning is diagrams, which uses a very sophisticated model for pictures, with a plethora of types and classes involved, and yet handles operations such as scaling in a similar manner.

Haskell - Creating rectangle of 1s with height and width of user input

I am trying to create a function that will take two integer values that correspond to the width and height of a rectangle of 1s that is outputted like so:
Main> rectangle 3 4
1111
1111
1111
I am a beginner at Haskell and have no experience, so any pointers would be appreciated, and therefore only basic Haskell operations should be used. Thanks.
rectangle :: Int -> Int -> String
rectangle h w = unlines (replicate h (replicate w '1'))
Although this is a pure function, it does show the relevant part. You can just putStrLn (rectangle 3 4) to have it printed out as expected in ghci, rather than wrapped in a show.
Giving it a second thought, here's a short walkthrough.
replicate :: Int -> a -> [a]
unlines :: [String] -> String
As you can see, replicate w '1'creates a list of w times the charakter 1. Because String = [Char], the result is a String of ones, as many as w says.
Now, this String is replicated again, h times, giving a list of h times that string.
unlines now concatenates those strings, inserting a new line character between the strings.
The result is what you'd expect, only that ghci (which you appear to be using) is wrapping each expression's result in a show call. So, to do exactly what you want to achieve, a call to putStr in needed as so:
impureRectangle :: Int -> Int -> IO ()
impureRectangle x y = putStr (rectangle x y)
Note that monads (or IO, as the first monad, people use to get to know as such) are not the easiest things to get your head around. I'd suggest staying pure until you feel safe.

How to add an element to a list of a data type in Haskell

I have defined two data types: Point and Curve. Point has two doubles for its coordinates and a Curve has a starting Point and a list of Points representing the rest of the Curve. I need to make a function that creates this Curve given a starting Point and a list of Points but I can't quite understand how am I supposed to add an element to the list of Points inside the Curve.
Here is my code:
data Point = Point Double Double deriving (Eq, Show)
point :: (Double, Double) -> Point
point (x, y) = Point x y
data Curve = Curve Point [Point] deriving (Eq, Show)
curve :: Point -> [Point] -> Curve
curve x [] = Curve x []
curve x [y] = Curve x [y]
curve x (y:ys) = curve x (y:ys)
I am pretty sure my recursion in the end is wrong. So could you give me maybe some guidelines on how to add a point in the list?
thanks
myCurve = Curve (Point 2 2) [Point 3 3, Point 4 4, Point 5 5]
Wait, what, you say? Indeed, Curve is already that function you want. It is both a type constructor (the left-hand-side in the data definition) and a value constructor (the right hand side.)
If you probe Curve with ghci, you will find...
Prelude> :t Curve
Curve :: Point -> [Point] -> Curve
The same goes for Point. In other words, the entirety of your code looks like this:
data Point = Point Double Double deriving (Eq, Show)
data Curve = Point [Point] deriving (Eq, Show)
EDIT: An ultra-small primer on value constructors.
When you create a new datatype, you automatically create a value constructor, which is a function that creates a value of the new type. It's not entirely clear in your example because the type and value constructors have the same name, which is permissible in Haskell because one lives in the type level and the other in the value level. Let's try and make it a bit more obvious:
data MyIntType = MakeIntType Int
Now, MakeIntType is a function that takes one argument, an Int, and creates a value of type MyIntType. Let's check that in ghci:
Prelude> :t MakeIntType
MakeIntType :: Int -> MyIntType
Now, we could write an identical function, like you're proposing:
makeIntType :: Int -> MyIntType
makeIntType x = MakeIntType x
or, dropping the explicit points (arguments):
makeIntType = MakeIntType
Both equation shows that we've duplicated work. There is no functional difference between makeIntType and MakeIntType. They are completely equivalent, and since you will always get the value constructor function "for free," makeIntType is a completely superfluous alias for something that's already there.
I hope that clears things up a bit.
Edit 2: Creating a new modified Curve based on an existing one
addPointToStartOfCurve p (Curve p' ps) = Curve p (p':ps)
Here, we create a new Curve from an existing one by pushing the first element of the existing Curve onto the list of points and adding a new starting point. Another variant would add a point to the end of an existing Curve.
addPointToEndOfCurve p (Curve p' ps) = Curve p' (ps ++ [p])
Note that because of immutability, the original curves aren't altered, we're just producing new values.

How to generate random triangle on a unit circle

I'm trying to find out the probability of the center of a unit circle falling inside a triangle. The vertexes of the triangle are randomly picked on the unit circle.
My idea is to pick a random float x in the range (-1.0, 1.0) and then randomly select up or down. This will get me one point (x, +/-sqrt(1 - x*x))
import Data.Random
main = do
x <- randomRIO (-1.0,1.0)
let y = (sample (randomElement [-1,1])) * sqrt(1-x*x)) -- I can't make this line work
So how do I select a random element from a [Int] ?
I don't speak Haskell, but to choose a point on a circle with even distribution, the variable you need to pick is the angle.
angle <- randomRIO(-pi, pi)
then
y = sin(angle)
x = cos(angle)
Pick 3 angles for your 3 dots and that gives you a random triangle.
As for testing if the center is in the triangle, I am fairly certain, though I have no demonstration so far, that you can go as follows:
Find the longest edge. The edge splits the circle in 2 parts
If the third vertex is in the smallest part, the center is not in the triangle
Else, it is
Edit, Demonstration
Let, ABC be a triangle in the circle of center D.
Let AB be the longest edge
Let C be on the largest half of the circle cut by AB
If D is not in ABC, then either AC or BC (for simplicity and since this is just naming convention, let assume AC) is the edge of the triangle that between AB and D
AC and AB being chords of the circle, the closest to the center is the longest
AC is longer than AB
How to apply this to angles only
From the previous demonstration, it quickly appears that if all 3 points are in the same half, the center is not in the triangle, otherwise it is.
The point is therefore to determine that the maximum distance between 2 points is pi.
Thanks to J. Abrahamson, we can compute the difference between all three points' angles, and sum the smaller two, return true if the sum is greater than pi.
The actual measurement of the distance between 2 points goes like this, as we need the absolute and most direct distance between the 2:
Compute the absolute distance diff = abs(theta1 - theta2)
If this is more than pi, use 2 * pi - diff
Look into the MonadRandom package, the uniform function will give you a random value from a list of values ([Int] in your case). I'm on my phone, but finding the package shouldn't be too tough. If you want to use a different distribution, look into random-fu.
An example of this using the MonadRandom package instead (cabal install MonadRandom):
import Control.Monad.Random
type R a = Rand StdGen a -- Just a type alias for less typing
type Point = (Double, Double)
type Triangle = (Point, Point, Point)
-- Monadic action
genAngle :: R Double
genAngle = getRandomR (-pi, pi)
-- Monadic action
genPoint :: R Point
genPoint = do
x <- genAngle
return (cos x, sin x)
-- Monadic action
genTriangle :: R Triangle
genTriangle = do
a <- genPoint
b <- genPoint
c <- genPoint
return (a, b, c)
-- Pure function
containsOrigin :: Triangle -> Bool
containsOrigin (a, b, c) = ??? -- You get to implement this (#njzk2 has given some pointers)
-- Monadic action
genTriangles :: R [Triangle]
genTriangles = do
tri <- genTriangle
rest <- genTriangles -- Recursion to get infinite list
return $ tri : rest
-- Monadic action
genTrianglesWithOrigin :: R [Triangle]
genTrianglesWithOrigin = do
triangles <- genTriangles
return $ filter containsOrigin triangles
main :: IO ()
main = do
triangles <- fmap (take 10) $ evalRandIO genTrianglesWithOrigin
mapM_ print triangles
If you want more reading on why MonadRandom is nicer than the base random package, I would recommend looking at this section of Learn You A Haskell. Basically, MonadRandom builds a nicer interface where not everything is in IO (which is dangerous, who knows what an IO function does) and provides some easy functions for generating random numbers, whereas the random package just provides the most barebones functionality possible. In fact, the Rand monad is nothing more than the State monad in disguise, it just keeps up with the state of your generator seed for you.

Resources