Haskell Function not accepting argument - haskell

I wrote a simple code to convert rgb to cmyk. Then I defined the datatype Color.
now I got this error:
Couldn't match expectet type `Color' with actual type `(t0, t1, t2)'
I thought Color would refer to Rgb(Int,Int,Int). What I have done wrong?
My code:
data Color = Rgb (Int,Int,Int) | Cmyk Double Double Double Double deriving (Show)
rgb2cmyk :: Color -> Color
rgb2cmyk (Rgb (0,0,0)) = (Cmyk 0 0 0 1)
rgb2cmyk (Rgb (r,g,b)) = (Cmyk c m y k)
where
rd = (fromIntegral r)/255
gd = (fromIntegral g)/255
bd = (fromIntegral b)/255
w = max3 rd gd bd
c = w - rd/w
m = w - gd/w
y = w - bd/w
k = 1 - w
max3 :: Double -> Double -> Double -> Double
max3 a b c | a>=b && a>=c = a
| b>=a && b>=c = b
| otherwise = c
test1 = rgb2cmyk 233 123 123
Error occours in test1 line. Do I have to write rgb2cmyk $ Rgb?

I would suggest to keep the syntax, keep Rgb Int Int Int instead of Rgb (Int,Int,Int)
data Color = Rgb Int Int Int | Cmyk Double Double Double Double deriving (Show)
rgb2cmyk :: Color -> Color
rgb2cmyk (Rgb 0 0 0) = (Cmyk 0 0 0 1)
rgb2cmyk (Rgb r g b) = (Cmyk c m y k)
where
(...)
*Main> rgb2cmyk $ Rgb 0 0 0
Cmyk 0.0 0.0 0.0 1.0
Explaining the comment:
You cant call rgb2cmyk as rgb2cmyk x y z, the function is expecting an Rgb x y z so you must call it as rgb2cmyk Rgb 10 10 10 for example. Rgb is a Color is a constructor and either Rgb or Cmyk must be called if your function takes a Color.

Related

Creating a picture of a map with a recurssive function

i'm using haskell gloss for the first time and I'm having some trouble, in this code:
-- the initial c and l will be imagine for dimension 9: (-160) 160
-- (so the square ends in the center of the window
-- column; line; dimension
drawmap :: Float -> Float -> Float -> Picture
drawmap c l d = (drawline x c l d) : (drawmap xs c (l+40) d)
drawline :: Float -> Float -> Float -> Picture
drawline c l d = if (d>0) then (Translate c l $ Color red (circle 20)) : (drawline (c+40) l (d-1))
else (Translate c l $ Color red (circle 20))
The only question I have right now is with the type, because I need it to be the type Picture, and not [Picture], any help?
And also, how do i make this stop point:
drawline _ _ 0 = Nothing or []
I know this is not acceptable, but how do I tell it when to stop doing circles?
This is not pratical at all, is just an example very simple, if someone helps me understand this I can after apply what I really need to do.

RGB to CMYK in Haskell

I'm suppposed to convert a given RGB color to CMYK format, and in case of white (0,0,0) I should get (0,0,0,1). I've been trying this whole night but every time it crashes, could please someone tell what's wrong?
rgb2cmyk :: (Int,Int,Int) -> (Float,Float,Float,Float)
rgb2cmyk (r,g,b) = (c,m,y,k)
| (r,g,b) == (0,0,0) = (0,0,0,1)
| otherwise = ((w - (r/255))/w, (w - (g/255))/w, (w - (b/255))/w, 1 - w)
where
w = maximum [r/255, g/255, b/255]
I get: parse error on input '|'
You want to say either
rgb2cmyk (r, g, b) = ...
or
rgb2cymk (r, g, b)
| ... = ...
| ... = ...
But not both at the same time. (Which expression would it execute?)
As an aside, you don't actually need to test (r,g,b) == (0,0,0); you can just pattern-match (0,0,0) directly.
rgb2cymk (0,0,0) = (0,0,0,1)
rgb2cymk (r,g,b) = ???
The section = (c, m, y, k) in rgb2cmyk (r,g,b) = (c,m,y,k) is incorrect.
When using guards, you should think of it as using something like
rgb2cmyk (r,g,b) = case (r,g,b) of
(0,0,0) -> (0,0,0,1)
_ -> ...
as this is what GHC will actually rewrite your guards into (this is the same with if, as well, which turns into case predicate of...).
It doesn't make sense to write
rgb2cmyk (r,g,b) = (c,m,y,k)
And then later on have:
case (r,g,b) of ...
sitting as a floating definition in your source file.

Haskell numerical integration via Trapezoidal rule results in wrong sign

I've written some code that's meant to integrate a function numerically using the trapezoidal rule. It works, but the answer it produces has a wrong sign. Why might that be?
The code is:
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + partial_sum)
where
h = (b - a) / 1000
most_parts = map f (points (1000-1) h)
partial_sum = sum most_parts
points :: Double -> Double -> [Double]
points x1 x2
| x1 <= 0 = []
| otherwise = (x1*x2) : points (x1-1) x2
Trapezoidal rule
The code is probably inelegant, but I'm only a student of Haskell and would like to deal with the current problem first and coding style matters after that.
Note: This answer is written in literate Haskell. Save it with .lhs as extension and load it in GHCi to test the solution.
Finding the culprit
First of all, let's take a look at integration. In its current form, it contains only summation of function values f x. Even though the factors aren't correct at the moment, the overall approach is fine: you evaluate f at the grid points. However, we can use the following function to verify that there's something wrong:
ghci> integration (\x -> if x >= 10 then 1 else (-1)) 10 15
-4.985
Wait a second. x isn't even negative in [10,15]. This suggests that you use the wrong grid points.
Grid points revisited
Even though you've linked the article, let's have a look at an exemplary use of the trapezoidal rule (public domain, original file by Oleg Alexandrov):
Although this doesn't use a uniform grid, let's suppose that the 6 grid points are equidistant with grid distance h = (b - a) / 5. What are the x coordinates of those points?
x_0 = a + 0 * h (== a)
x_1 = a + 1 * h
x_2 = a + 2 * h
x_3 = a + 3 * h
x_4 = a + 4 * h
x_5 = a + 5 * h (== b)
If we use set a = 10 and b = 15 (and therefore h = 1), we should end up with [10, 11, 12, 13, 14, 15]. Let's check your points. In this case, you would use points 5 1 and end up with [5,4,3,2,1].
And there's the error. points doesn't respect the boundary. We can easily fix this by using pointsWithOffset:
> points :: Double -> Double -> [Double]
> points x1 x2
> | x1 <= 0 = []
> | otherwise = (x1*x2) : points (x1-1) x2
>
> pointsWithOffset :: Double -> Double -> Double -> [Double]
> pointsWithOffset x1 x2 offset = map (+offset) (points x1 x2)
That way, we can still use your current points definition to generate grid points from x1 to 0 (almost). If we use integration with pointsWithOffset, we end up with
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + partial_sum)
where
h = (b - a) / 1000
most_parts = map f (pointsWithOffset (1000-1) h a)
partial_sum = sum most_parts
Tying up loose ends
However, this doesn't take into account that you use all inner points twice in the trapezoid rule. If we add the factors, we end up with
> integration :: (Double -> Double) -> Double -> Double -> Double
> integration f a b =
> h / 2 * (f a + f b + 2 * partial_sum)
> -- ^^^ ^^^
> where
> h = (b - a) / 1000
> most_parts = map f (pointsWithOffset (1000-1) h a)
> partial_sum = sum most_parts
Which yields the correct value for our test function above.
Exercise
Your current version only supports 1000 grid points. Add an Int argument so that one can change the number of grid points:
integration :: Int -> (Double -> Double) -> Double -> Double -> Double
integration n f a b = -- ...
Furthermore, try to write points in different ways, for example go from a to b, use takeWhile and iterate, or even a list comprehension.
Yes it indeed was the points plus you had some factors wrong (the inner points are multiplied by 2) - this is the fixed version of your code:
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + innerSum) / 2
where
h = (b - a) / 1000
innerPts = map ((2*) . f . (a+)) (points (1000-1) h)
innerSum = sum innerPts
points :: Double -> Double -> [Double]
points i x
| i <= 0 = []
| otherwise = (i*x) : points (i-1) x
which gives sensible approximations (to 1000 points):
λ> integration (const 2) 1 2
2.0
λ> integration id 1 2
1.5
λ> integration (\x -> x*x) 1 2
2.3333334999999975
λ> 7/3
2.3333333333333335

Rendering a texture on screen

I'm new to both Haskell and OpenGL and I'm trying to render a texture on the screen.
Here's what I've got so far:
makeTexture :: FilePath -> IO GL.TextureObject
makeTexture f = do
t <- either error id <$> GLU.readTexture f
GL.textureFilter GL.Texture2D GL.$= ((GL.Linear', Nothing), GL.Linear')
GLU.texture2DWrap GL.$= (GL.Mirrored, GL.ClampToEdge)
return t
renderEntity :: Entity -> IO ()
renderEntity e = do
GL.activeTexture GL.$= GL.TextureUnit 0
GL.textureBinding GL.Texture2D GL.$= Just (texture $ model e)
-- I see a white triangle on the screen.
renderTriangle $ fmap (vadd $ position e) (points $ model e :: [Vector2])
-- I do not see this. Nor is the triangle textured either.
GL.renderPrimitive GL.Quads $ do
n 0 1 0
t 0 1 >> v 10 (-10) 10
t 1 1 >> v 10 (-10) (-10)
t 1 0 >> v (-10) (-10) (-10)
t 0 0 >> v (-10) (-10) 10
where v x y z = GL.vertex (GL.Vertex3 x y z :: GL.Vertex3 GL.GLfloat)
n x y z = GL.normal (GL.Normal3 x y z :: GL.Normal3 GL.GLfloat)
t u v = GL.texCoord (GL.TexCoord2 u v :: GL.TexCoord2 GL.GLfloat)
Where Entity looks like:
texMetal <- makeTexture "texture/metal.jpg"
let
entity = Entity
{ angle = 0
, position = (0, 0) :: Vector2
, velocity = (5, 5) :: Vector2
, model = Model
{ points = [(-60, -40), (60, -40), (0, 60)] :: [Vector2]
, texture = texMetal
}
}
And when I'm initializing I have these:
GL.viewport GL.$= (pos, size)
GL.matrixMode GL.$= GL.Projection
GL.texture GL.Texture2D GL.$= GL.Enabled
GL.normalize GL.$= GL.Enabled
GL.loadIdentity
GL.ortho2D (-fromIntegral width / 2)
(fromIntegral width / 2)
(-fromIntegral height / 2)
(fromIntegral height / 2)
GL.matrixMode GL.$= GL.Modelview 0
GL.loadIdentity
And the resulting picture:
It has two triangles because I have two 'entities' set in my code. But I don't see my quad nor do I see any sign of texturing.
It seems I had incorrect coordinates, because this works well:
renderEntity :: Entity -> IO ()
renderEntity e = do
GL.activeTexture GL.$= GL.TextureUnit 0
GL.textureBinding GL.Texture2D GL.$= Just (texture $ model e)
GL.renderPrimitive GL.Quads $ do
v 100 100
t 0 1
v 100 (-100)
t 1 1
v (-100) (-100)
t 1 0
v (-100) 100
t 0 0
where v x y = GL.vertex (GL.Vertex2 x y :: GL.Vertex2 GL.GLfloat)
t u v = GL.texCoord (GL.TexCoord2 u v :: GL.TexCoord2 GL.GLfloat)

recursive haskell function hangs forever in interactive session

I have a recursive function that plots some picture in ASCII art. It is quite simple being
type Picture = [[Char]]
white :: Picture
white = ["......",
"......",
"......",
"......",
"......",
"......"]
black = ["######",
"######",
"######",
"######",
"######",
"######"]
printPicture :: Picture -> IO ()
printPicture = putStr . concat . map (++"\n")
With these blocks I want to construct a game board. I have define some functions to do so, which are:
blackinWhite :: Integer -> Integer -> Picture
blackinWhite n m | n==1 && m==1 = black
| n==1 = white
| n==m = black `beside` blackinWhite (n-1) m
| otherwise = white `beside` blackinWhite (n-1) m
blackinWhite' :: Integer -> Integer -> Picture
blackinWhite' n m | n==1 && m==1 = black
| n==1 = white
| n==m = black `above` blackinWhite' (n-1) m
| otherwise = white `above` blackinWhite' (n-1) m
diagonalrug :: Integer -> Integer -> Picture
diagonalrug n m | m==1 = blackinWhite n m
| otherwise = blackinWhite n m `above` diagonalrug n (m-1)
antidiagrug :: Integer -> Integer -> Picture
antidiagrug n m | m==1 = blackinWhite' n m
| otherwise = antidiagrug n (m-1) `beside` blackinWhite' n m
crossedrug :: Integer -> Integer -> Picture
crossedrug n m | dimn /= 0 || dimm /= 0= error("Come back later")
| otherwise = diagonalrug dimn dimm --((diagonalrug dimn dimm) `beside` (antidiagrug dimn dimm)) `above` ((antidiagrug dimn dimm) `beside` (diagonalrug dimn dimm))
where
dimn = mod n 2
dimm = mod m 2
If I do in the interactive session:
*Main> diagonalrug 2 2
The program hangs and my computer is freezed. If I execute directly the statement that comes after otherwise, the result is given without any problems. Why if I call the function crossedrug ghci crashes?
(I am not providing the functions above and beside, since they simply concatenate two pictures that should be clear from the context.)
Just follow execution.
You're calling it with 2 2, it goes to the otherwise and calls diagonalrug 0 0 which in turn goes to the otherwise clause which never terminates since it calls diagonalrug 0 -1 so m is never 1 (it keeps being negative).
diagonalrug is missing a stopping condition for that case.

Resources