RGB to CMYK in Haskell - 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.

Related

Haskell, why do I get a prelude undefined error?

this is an exercise where I have to create my own universe of things in Haskell for a logic course. This was given to us already:
data Thing = A | B | C | D | E deriving (Eq,Show)
things :: [Thing]
things = [ A, B, C, D, E ]
data Colour = Amber | Blue deriving Eq
colour :: Thing -> Colour
colour A = Amber
colour B = Amber
colour C = Amber
colour D = Blue
colour E = Amber
data Shape = Square | Disc deriving Eq
shape :: Thing -> Shape
shape A = Square
shape B = Square
shape C = Disc
shape D = Square
shape E = Square
data Size = Big | Small deriving Eq
size :: Thing -> Size
size A = Big
size B = Big
size C = Big
size D = Big
size E = Small
data Border = Thin | Thick deriving Eq
border :: Thing -> Border
border A = Thick
border B = Thin
border C = Thick
border D = Thick
border E = Thick
type Predicate u = u -> Bool
isAmber :: Predicate Thing
isAmber x = colour x == Amber
isBlue :: Predicate Thing
isBlue x = colour x == Blue
isSquare :: Predicate Thing
isSquare x = shape x == Square
isDisc :: Predicate Thing
isDisc x = shape x == Disc
isBig :: Predicate Thing
isBig x = size x == Big
isSmall :: Predicate Thing
isSmall x = size x == Small
hasThinBorder :: Predicate Thing
hasThinBorder x = border x == Thin
hasThickBorder :: Predicate Thing
hasThickBorder x = border x == Thick
The following function was also given as an example of predicate negation :
neg :: Predicate u -> Predicate u
(neg a) x = not (a x)
I have to write 2 functions, one for conjunction (only true & true = true, all else is false) and disjunction (only false & false = true). I was pretty sure that this was correct, but i get the prelude undefined error when I call:
(|:|) :: Predicate u -> Predicate u -> Predicate u
(a |:| b) x = (a x) && (b x)
(&:&) :: Predicate u -> Predicate u -> Predicate u
(a &:& b) x = (a x) || (b x)
(|=) :: Predicate Thing -> Predicate Thing -> Bool
a |= b = [thinga | thinga <- things, a thinga] == [thingb | thingb <- things, b thingb, a thingb]
(|/=) :: Predicate Thing -> Predicate Thing -> Bool
a |/= b = not (a |= b)
But also, the instructions say that calling the following should work, and i do not understand how, since the x formal parameter is never used...
isBig &:& isAmber |= isDisc
That should return either true or false apparently
Example of Error
*Main> :reload
Ok, one module loaded.
*Main> isSmall |= isDisc
False
*Main> (neg isAmber) C
False
*Main> (isBig &:& isAmber) |= isDisc
*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries\base\GHC\Err.hs:79:14 in base:GHC.Err
undefined, called at things.hs:89:15 in main:Main
I'm focusing on this part:
and i do not understand how, since the x formal parameter is never
used...
isBig &:& isAmber |= isDisc
That should return either true or false apparently
The value of x is chosen by |=, which will call both predicates isBig &:& isAmber and isDisc with all the x in list things.
Expanding the definitions:
isBig &:& isAmber |= isDisc
= -- according to the definition of |=
[thinga | thinga <- things, (isBig &:& isAmber) thinga]
==
[thingb | thingb <- things, isDisc thingb, (isBig &:& isAmber) thingb]
= -- according to the definition of &:&
[thinga | thinga <- things, isBig thinga && isAmber thinga]
==
[thingb | thingb <- things, isDisc thingb, isBig thingb && isAmber thingb]
=
[ A, B, C ] -- i.e., list of all things which are both big and amber
==
[ C ] -- i.e., list of all things which are discs, big, and amber
=
False -- the two lists are not the same list
So, it's thinga and thingb that are passed as x. Those variables, in turn, assume all the values inside the list things, i.e. [A,B,C,D,E].

Generate a random list of custom data type, where values provided to data constructor are somehow bounded within a range

I have defined a Point data type, with a single value constructor like so:
data Point = Point {
x :: Int,
y :: Int,
color :: Color
} deriving (Show, Eq)
data Color = None
| Black
| Red
| Green
| Blue
deriving (Show, Eq, Enum, Bounded)
I have found an example of making a Bounded Enum an instance of the Random class and have made Color an instance of it like so:
instance Random Color where
random g = case randomR (1, 4) g of
(r, g') -> (toEnum r, g')
randomR (a, b) g = case randomR (fromEnum a, fromEnum b) g of
(r, g') -> (toEnum r, g')
I was then able to find out how to make Point an instance of the Random class also:
instance Random Point where
randomR (Point xl yl cl, Point xr yr cr) g =
let (x, g1) = randomR (xl, xr) g
(y, g2) = randomR (yl, yr) g1
(c, g3) = randomR (cl, cr) g2
in (Point x y c, g3)
random g =
let (x, g1) = random g
(y, g2) = random g1
(c, g3) = random g2
in (Point x y c, g3)
So, this let's me make random point values. But, what I'd like to do is be able to create a list of random Point values, where the x and the y properties are bounded within some range whilst leaving the color property to be an unbounded random value. Is this possible with the way I am currently modelling the code, or do I need to rethink how I construct Point values? For instance, instead of making Point an instance of the Random class, should I just create a random list of Int in the IO monad and then have a pure function that creates n Points, using values from the random list to construct each Point value?
Edit, I think I have found out how to do it:
Without changing the above code, in the IO monad I can do the following:
solved :: IO ()
solved = do
randGen <- getStdGen
let x = 2
let randomPoints = take x $ randomRs (Point 0 0 None, Point 200 200 Blue) randGen
putStrLn $ "Random points: " ++ show randomPoints
This seems to work, randomRs appears to let me specify a range...
Presumably because my Point data type derives Eq?
Or
Is it because my x and y properties are Int (guessing here, but may be "bounded" by default) and I have Color derive bounded?
It works because of the properties of the Int and Color types, not because of the properties of Point. If one suppresses the Eq clause of Point, it still works.
Your code is overall quite good, however I would mention a few minor caveats.
In the Random instance for Point, you are chaining the generator states manually; this is a bit error prone, and monadic do notation is supposed to make it unnecessary. The Color instance could be simplified.
You are using IO where it is not really required. IO is just one instance of the MonadRandom class. If g is an instance of RandomGen, any Rand g is an instance of MonadRandom.
The random values you're getting are not reproducible from a program execution to the next one; this is because getStdGen implicitly uses the launch time as a random number generation seed. It may do that because it is IO-hosted. In many situations, this is a problem, as one might want to vary the choice of random sequence and the system parameters independently of each other.
Using monadic style, the basics of your code could be rewritten for example like this:
import System.Random
import System.Random.TF -- Threefish random number generator
import Control.Monad.Random
data Point = Point {
x :: Int,
y :: Int,
color :: Color
} deriving (Show, Eq)
data Color = None
| Black
| Red
| Green
| Blue
deriving (Show, Eq, Enum, Bounded)
instance Random Color where
randomR (a, b) g = let (r,g') = randomR (fromEnum a, fromEnum b) g
in (toEnum r, g')
random g = randomR (minBound::Color, maxBound::Color) g
singleRandomPoint :: -- monadic action for just one random point
MonadRandom mr => Int -> Int -> Color -> Int -> Int -> Color -> mr Point
singleRandomPoint xmin ymin cmin xmax ymax cmax =
do
-- avoid manual chaining of generator states:
x <- getRandomR (xmin, xmax)
y <- getRandomR (ymin, ymax)
c <- getRandomR (cmin, cmax)
return (Point x y c)
And then we can derive an expression returning an unlimited list of random points:
-- monadic action for an unlimited list of random points:
seqRandomPoints :: MonadRandom mr =>
Int -> Int -> Color -> Int -> Int -> Color -> mr [Point]
seqRandomPoints xmin ymin cmin xmax ymax cmax =
sequence (repeat (singleRandomPoint xmin ymin cmin xmax ymax cmax))
-- returns an unlimited list of random points:
randomPoints :: Int -> Int -> Int -> Color -> Int -> Int -> Color -> [Point]
randomPoints seed xmin ymin cmin xmax ymax cmax =
let
-- get random number generator:
-- using Threefish algorithm (TF) for better statistical properties
randGen = mkTFGen seed
action = seqRandomPoints xmin ymin cmin xmax ymax cmax
in
evalRand action randGen
Finally we can print the first few random points on stdout:
-- Small printing utility:
printListAsLines :: Show t => [t] -> IO()
printListAsLines xs = mapM_ (putStrLn . show) xs
solved01 :: IO ()
solved01 = do
let
seed = 42 -- for random number generator setup
-- unlimited list of random points:
allRandomPoints = randomPoints seed 0 0 None 200 200 Blue
count = 5
someRandomPoints = take count allRandomPoints
-- IO not used at all so far
putStrLn $ "Random points: "
printListAsLines someRandomPoints
main = solved01
Program execution (reproducible with constant seed):
$ randomPoints
Random points:
Point {x = 187, y = 56, color = Green}
Point {x = 131, y = 28, color = Black}
Point {x = 89, y = 135, color = Blue}
Point {x = 183, y = 190, color = Red}
Point {x = 27, y = 161, color = Green}
$
Should you prefer to just get a finite number of points and also get back the updated state of your random number generator, you would have to use replicate n instead of repeat, and runRand instead of evalRand.
Bit more details about the monadic approach here.

How would I remove borders from all Floating windows in XMonad

There are several similar questions but none quite solve it for me, for example this question explains how to remove borders from fullscreen floating windows.
Using XMonad.Layout.NoBorders you can do lots of cool stuff like remove borders from certain windows or if it is the only window or only fullscreen floating windows.
I couldn't find anything for all floating windows, however if someone could just point me to some tool that I could use to check if a window is floating or not, I am sure I could try hack up a solution.
Any suggestions are welcome
I'll be using the source code of XMonad.Layout.NoBorders as a reference, since I can't find anything more fitting that already exists. We want to see how it implements "remove borders on fullscreen floating windows", to see if it can be easily relaxed to "remove borders on floating windows" (without the fullscreen constraint).
According to the answer on the question you linked:
layoutHook = lessBorders OnlyFloat $ avoidStruts $ myLayout
OnlyFloat seems to be the specifier for "remove borders on fullscreen floating windows", so let's check the definition of that:
data Ambiguity = Combine With Ambiguity Ambiguity
| OnlyFloat
| Never
| EmptyScreen
| OtherIndicated
| Screen
deriving (Read, Show)
Not too helpful on its own. We should look elsewhere to see how the code treats these values.
It's a pretty safe bet that the first function to check is lessBorders:
lessBorders :: (SetsAmbiguous p, Read p, Show p, LayoutClass l a) =>
p -> l a -> ModifiedLayout (ConfigurableBorder p) l a
lessBorders amb = ModifiedLayout (ConfigurableBorder amb [])
From the type signature of lessBorders, we can see that:
OnlyFloat :: (SetsAmbiguous p, Read p, Show p) => p
This is a good sign, as it means lessBorders doesn't explicitly expect an Ambiguity: we can extend the functionality here by implementing our own SetsAmbiguous and passing it to the existing lessBorders. Let's now look at SetsAmbiguous, and Ambiguity's implementation of it:
class SetsAmbiguous p where
hiddens :: p -> WindowSet -> Maybe (W.Stack Window) -> [(Window, Rectangle)] -> [Window]
instance SetsAmbiguous Ambiguity where
hiddens amb wset mst wrs
| Combine Union a b <- amb = on union next a b
| Combine Difference a b <- amb = on (\\) next a b
| Combine Intersection a b <- amb = on intersect next a b
| otherwise = tiled ms ++ floating
where next p = hiddens p wset mst wrs
nonzerorect (Rectangle _ _ 0 0) = False
nonzerorect _ = True
screens =
[ scr | scr <- W.screens wset,
case amb of
Never -> True
_ -> not $ null $ integrate scr,
nonzerorect . screenRect $ W.screenDetail scr]
floating = [ w |
(w, W.RationalRect px py wx wy) <- M.toList . W.floating $ wset,
px <= 0, py <= 0,
wx + px >= 1, wy + py >= 1]
ms = filter (`elem` W.integrate' mst) $ map fst wrs
tiled [w]
| Screen <- amb = [w]
| OnlyFloat <- amb = []
| OtherIndicated <- amb
, let nonF = map integrate $ W.current wset : W.visible wset
, length (concat nonF) > length wrs
, singleton $ filter (1==) $ map length nonF = [w]
| singleton screens = [w]
tiled _ = []
integrate y = W.integrate' . W.stack $ W.workspace y
hiddens is the only method here that we need to implement. Its arguments are our SetsAmbiguous value, a WindowSet, and some other things, and it returns a list of windows that should not show borders. There's a lot of logic for the combining operations and other Ambiguity values, but those don't matter to us right now. What we care about is this snippet:
floating = [ w |
(w, W.RationalRect px py wx wy) <- M.toList . W.floating $ wset,
px <= 0, py <= 0,
wx + px >= 1, wy + py >= 1]
This is very promising. It defines a set of floating windows by extracting all windows from the floating section of the WindowSet, converting it to a list (initially it's a Data.Map), and filtering out all the windows that don't cover the entire screen. All we need to do is remove the filter.
After making that change, and removing all unnecessary code pertaining to tiled windows and set operations (which is most of the implementation), we end up with simply:
import XMonad.Layout.NoBorders
import qualified XMonad.StackSet as W
import qualified Data.Map as M
data AllFloats = AllFloats deriving (Read, Show)
instance SetsAmbiguous AllFloats where
hiddens _ wset _ _ = M.keys $ W.floating wset
We can then say:
layoutHook = lessBorders AllFloats $ myLayout...

Haskell implementation of De-convolution (Richardson lucy)

I'm trying to implement an algorithm of de-convolution in Haskell and couldn't find a simpler one than Richardson Lucy. I looked up at the existing matlab/python implementation but am unable to understand from where to start or how exactly to implement.
The library I want to use is https://github.com/lehins/hip.
If someone can provide an outline of some implementation or some general idea about the functions with some code snippets, that would be very helpful to me.
Thanks in advance!
The algorithm is actually pretty straightforward. Using the notation on the Wikipedia page for Richardson-Lucy deconvolution, if an underlying image u0 was convolved by a kernel p to produce an observed image d, then you can iterate the function:
deconvolve p d u = u * conv (transpose p) (d / conv p u)
over u with an initial starting estimate (of d, for example) to get a progressively better estimate of u0.
In HIP, the actual one-step deconvolve function might look like:
deconvolve :: Image VS X Double
-> Image VS RGB Double
-> Image VS RGB Double
-> Image VS RGB Double
deconvolve p d u
= u * conv (transpose p) (d / conv p u)
where conv = convolve Edge
and you could use something like this:
let us = iterate (deconvolve p d) d
u10 = us !! 10 -- ten iterations
An example of a full program is:
import Graphics.Image as I
import Graphics.Image.Interface as I
import Prelude as P
blur :: Image VS X Double
blur = blur' / scalar (I.sum blur')
where blur' = fromLists [[0,0,4,3,2]
,[0,1,3,4,3]
,[1,2,3,3,4]
,[0,1,2,1,0]
,[0,0,1,0,0]]
deconvolve :: Image VS X Double
-> Image VS RGB Double
-> Image VS RGB Double
-> Image VS RGB Double
deconvolve p d u
= u * conv (transpose p) (d / conv p u)
where conv = convolve Edge
main :: IO ()
main = do
-- original underlying image
u0 <- readImage' "images/frog.jpg" :: IO (Image VS RGB Double)
-- the kernel
let p = blur
-- blurred imaged
let d = convolve Edge p u0
-- iterative deconvolution
let us = iterate (deconvolve p d) d
u1 = us !! 1 -- one iteration
u2 = us !! 20 -- twenty iterations
let output = makeImage (rows u0, cols u0 * 4)
(\(r,c) ->
let (i, c') = c `quotRem` cols u0
in index ([u0,d,u1,u2] !! i) (r,c'))
:: Image VS RGB Double
writeImage "output.jpg" output
which generates the following image of (left-to-right) the original frog, the blurred frog, a one-fold deconvolution, and a twenty-fold deconvolution.

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.

Resources