I need to create a list of tuples, each tuple represents a rectangle with (x, y, height,width).
With width constant, and I need to double the value of the height.
The output necessary:
> genRects 3 (0,0)
[(0.0,0.0,5.5,5.5),(5.5,0.0,5.5,5.5),(11.0,0.0,5.5,5.5),(16.5,0.0,5.5,5.5)]
My Currently code:
genRects :: Int -> (Int,Int) -> [(Float,Float,Float,Float)]
genRects 0 _ = []
genRects n (x,y) = let height=5.5; width=5.5 in [(fromIntegral x, fromIntegral y, height, width)] genRects (n-1) (x+height, y)
Getting error:
Couldn't match expected type `(Int->(Int, Int)-> [(Float, Float, Float, Float)])
-> Int -> (Int, Int) -> [(Float, Float, Float, Float)]'
with actual type `[(Integer, Integer, Double, Double)]'
The function `[(fromIntegral x, fromIntegral y, height, width)]'
is applied to three arguments,
but its type `[(Integer, Integer, Double, Double)]' has none
In the expression:
[(fromIntegral x, fromIntegral y, altura, comp)]
genRects (n - 1) (x + x, y)
In the expression:
let
height= 5.5
width = 5.5
in
[(fromIntegral x, fromIntegral y, height, width)]
genRects (n - 1) (x + x, y)
Failed, modules loaded: none.
Also why is it going to double instead of Float?
Have a look at
[(fromIntegral x, fromIntegral y, height, width)] genRects (n-1) (x+height, y)
That doesn't make sense. What you are trying to do is create one of the rectangles, and cons it on to all of the other rectangles, so you should use something like
(fromIntegral x, fromIntegral y, height, width): genRects (n-1) (x+height, y)
However, after making this change, you will see that
Couldn't match expected type `Int' with actual type `Float'
In the second argument of `(+)', namely `height'
In the expression: x + height
In the second argument of `genRects', namely `(x + height, y)'
Which makes sense, you are trying to add a Float (5.5) to the x value, which you have said is an Int. The simplest solution is to use Floats for x,y, instead of Ints.
So you can change your code to,
genRects :: Int -> (Float,Float) -> [(Float,Float,Float,Float)]
genRects 0 _ = []
genRects n (x,y) = let height=5.5; width=5.5 in (x, y, height, width): genRects (n-1) (x+height, y)
And get the desired result.
Any time you have a function which creates n of something where n is an explicit parameter to the function, ask yourself if you could instead write it as:
take n $ some_infinite_list
where some_infinite_list is an expression which creates an infinite list of the somethings.
For instance, here is the pattern of calls created by genRects n (x,y):
genRects n (x,y)
calls genRects (n-1) (x+h,y) -- h = height
calls genRects (n-2) (x+h+h, y)
calls genRects (n-3) (x+h+h+h, y)
...
So if we start with the sequence:
xys = [ (x,y), (x+h, y), (x+h+h, y), (x+3*h, y), ... ]
and create a function to4Tuple:
to4Tuple :: (Int,Int) -> (Float,Float,Float,Float)
mapping a pair (x,y) to your 4-tuple of floating point numbers, we can write genRects as:
genRects n (x0,y0) = take n $ map to4Tuple sys
where xys = [ (x,y0) | x <- [x0, x0+h .. ] ]
to4Tuple (x,y) = ...construct 4-tuple from x,y here...
Now you've avoided explicit recursion in the definition of genRects.
In
[(fromIntegral x, fromIntegral y, height, width)] genRects (n - 1) (x + x, y)
you are applying a list to three arguments. Lists are not functions and cannot be applied like that. GHC is talking about Double because you've confused it and when it doesn't know what sort of floating point it's supposed to be dealing with, it defaults to Double.
Side note: unless you're dealing with algorithms specialty tuned for single precision floating point, or dealing with special library functions that require such, or using unboxed arrays of them to save on space, you should really be using Double in your code.
Related
Task is to find all two-valued numbers representable as the sum of the sqrt's of two natural numbers.
I try this:
func = [sqrt (x) + sqrt (y) | x <- [10..99], y <- [10..99], sqrt (x) `mod` 1 == 0, sqrt (y) `mod` 1 == 0]
Result:
Unresolved top-level overloading Binding : func
Outstanding context : (Integral b, Floating b)
How can I fix this?
This happens because of a conflict between these two types:
sqrt :: Floating a => a -> a
mod :: Integral a => a -> a -> a
Because you write mod (sqrt x) 1, and sqrt is constrained to return the same type as it takes, the compiler is left trying to find a type for x that simultaneously satisfies the Floating constraint of sqrt and the Integral constraint of mod. There are no types in the base library that satisfy both constraints.
A quick fix is to use mod' :: Real a => a -> a -> a:
import Data.Fixed
func = [sqrt (x) + sqrt (y) | x <- [10..99], y <- [10..99], sqrt (x) `mod'` 1 == 0, sqrt (y) `mod'` 1 == 0]
However, from the error you posted, it looks like you may not be using GHC, and mod' is probably a GHC-ism. In that case you could copy the definition (and the definition of the helper function div') from here.
But I recommend a more involved fix. The key observation is that if x = sqrt y, then x*x = y, so we can avoid calling sqrt at all. Instead of iterating over numbers and checking if they have a clean sqrt, we can iterate over square roots; their squares will definitely have clean square roots. A straightforward application of this refactoring might look like this:
sqrts = takeWhile (\n -> n*n <= 99)
. dropWhile (\n -> n*n < 10)
$ [0..]
func = [x + y | x <- sqrts, y <- sqrts]
Of course, func is a terrible name (it's not even a function!), and sqrts is a constant we could compute ourselves, and is so short we should probably just inline it. So we might then simplify to:
numberSums = [x + y | x <- [4..9], y <- [4..9]]
At this point, I would be wondering whether I really wanted to write this at all, preferring just
numberSums = [8..18]
which, unlike the previous iteration, doesn't have any duplicates. It has lost all of the explanatory power of why this is an interesting constant, though, so you would definitely want a comment.
-- sums of pairs of numbers, each of whose squares lies in the range [10..99]
numberSums = [8..18]
This would be my final version.
Also, although the above definitions were not parameterized by the range to search for perfect squares in, all the proposed refactorings can be applied when that is a parameter; I leave this as a good exercise for the reader to check that they have understood each change.
So I'm trying to create a helper function that does something else, but I can't even get past the helper function because I keep getting this error:
Couldn't match expected type ‘[Char]’ with actual type ‘Int -> [t -> t1]’
freqsHelper x = freqs (x (lowers x))
^
The lowers(x) is causing the issue. Here is my code:
lowers [] = 0
lowers (x:xs)
| isLower x == True = 1 + lowers xs
| otherwise = lowers xs
count _ [] = 0
count x (y:ys)
| x == y = 1 + count x ys
| otherwise = count x ys
percent x y = x/y*100
freqsHelper x = freqs (x (lowers x))
freqs (x:xs) y = percent ((count (x (x:xs))) y) : freqs xs y
You’d be well-advised to add type declarations for every top-level function. Let’s follow what the type deduction system is doing here when it tries to figure this out.
The problem is not with lowers, which takes a [Char] as its argument and returns an Int.
The freqsHelper x declaration has one argument, x, whose type we’ll call a while we try to figure it out. We’ll call the return type b. So, freqsHelper is a function of type a -> b.
It’s also equal to freqs (x (lowers x)). So, x, which has type a, must be a function which takes the result of lowers as its argument. We know that lowers is [Char] -> Int, so a must be a function of type Int -> t1, where t1 is some type we would need to deduce from freqs. However, x is also passed as the argument of lowers. Which expects [Char], not a function with one argument. So we already have a contradiction.
So, there’s your mismatch. In the definition of freqsHelper, you’re using x in a context where Haskell expects a string, but also in a context where x has to be some kind of function. I’m pretty sure there’s a bug in freqs as well, given that it calls a function of two numeric arguments with only one argument.
Ah, I think I know what you're getting at. You're close. A couple things - if you're gonna do a division, you should do a fromIntegral to get back some kind of fractional.
percent :: (Fractional a) => Int -> Int -> a
percent x y = (fromIntegral x / fromIntegral y) * 100
I think your frequency is trying to get the frequency of something in a list, in which case you'll need a base case:
freqs [] y = []
freqs (x:xs) y = percent (count x y) (length y) : freqs xs y
I think you can figure out the rest from here.
A few style hints - you can use a map for freqs:
freqs' x y = map (\a -> percent (count a y) $ length y) x
The compiler will probably do it for you, but you can explicitly call out length y:
freqs' x y = map (\a -> percent (count a y) len) x
where len = length y
freqsHelper x = freqs (x (lowers x))
Let's break this down.
lowers x
You call lowers with x as input, so x must be a string.
x (lowers x)
But you call x as a function, passing it the result of lowers as input. So x must be a function that takes an Int as input. (That sounds like a mistake...)
freqs (x (lowers x))
You call freqs with the output from calling the x function... so x must return a list of some kind?
At this point, the type checker is confused as to what the heck x is even supposed to be, so it gives up.
Perhaps you meant to pass x and lowers x as two separate arguments? In that case, you want
freqs x (lowers x)
By putting brackets around x (lowers x), you make the compiler think that x is a function you want to call, with lowers x as the argument. I doubt you meant to do that.
As a side note, if you add type signatures on each of the functions you've defined, you may get a clearer indication from the type checker as to which bit is actually wrong. (As it is, the type checker can see the types don't line up, but can't actually determine where the types deviate from what you intended — because it cannot read your mind to know what you intended...)
I'm trying to understand how paralleling in Haskell works and I've found following example in Control.Parallel docs.
import Control.Parallel
-- Equation for the upper hemisphere of the unit circle
circle :: Double -> Double
circle x = sqrt (abs(1 - x^2))
-- Calculate the area of a right-handed Riemann rectangle
area :: Double -> Double -> Double
area x1 x2 = (x2 - x1) * circle x2
-- Recursively add the areas of the Riemann rectangles
parEstimate :: [Double] -> Double
parEstimate (x:[]) = 0
parEstimate (x:y:[]) = area x y
parEstimate (x:y:xs) =
smaller `par` (larger `pseq` smaller + larger)
where smaller = area x y
larger = parEstimate (y:xs)
But I couldn't find an explanation of how this recursion works: parEstimate (x:y:xs), cause all examples I've found contains only two arguments.
That's why I cannot find out how to run this function. That's how I do:
main = print (parEstimate [1.0, 2.0])
but not sure, if it's correct.
Also I would like to implement function calculating definite integral based on this example.
The recursion, essentially, is a simple fold-like recursion scheme; if this were purely sequential, you might write it as
seqEstimate :: [Double] -> Double
seqEstimate (x:[]) = 0
seqEstimate (x:y:[]) = area x y
seqEstimate (x:y:xs) = smaller + larger
where smaller = area x y
larger = seqEstimate (y:xs)
(In fact, you would probably just use zipWith instead: seqEstimate xs = sum (zipWith area xs (tail xs)).)
The parallelized version is similar. This time, though, par is used to indicate that the left-hand side (smaller) can be evaluated in parallel with the right-hand side (pseq larger (smaller + larger)). Whether or not the compiler chooses to do so, and regardless of whether smaller completes before or after larger, the sum of smaller + larger will be correctly computed.
I'm very new to haskell, writing a simple code that returns how many inputs are larger than their average value. I got error:
ERROR file:.\AverageThree.hs:5 - Type error in application
* Expression : x y z
Term : x
Type : Int
* Does not match : a -> b -> c
Code:
averageThree :: Int -> Int -> Int -> Float
averageThree x y z = (fromIntegral x+ fromIntegral y+ fromIntegral z)/3
howManyAverageThree ::Int -> Int -> Int -> Int
howManyAverageThree x y z = length > averageThree
Anyone help me?
The trouble you're having comes from a few places.
First, you aren't applying either function, length or averageThree - and hence also not using your arguments to howManyAverageThree.
Second, the type of length is [a] -> Int. As you don't have a list here, you either have to use a different function, or make a list.
If I understand your desired algorithm correctly, you are going to need to do a few things:
Apply x y and z to averageThree.
Use the filter function, comparing this computed average with each passed in parameter; this will result in a list.
Find the length of the resulting list.
The code I dashed off to do this follows:
howManyAverageThree ::Int -> Int -> Int -> Int
howManyAverageThree x y z = length $ filter (> avg) the_three
where avg = averageThree x y z
the_three = [fromIntegral x,fromIntegral y,fromIntegral z]
This takes advantage of a couple of neat features:
Currying, sometimes called "partial function application". That's what I was using with (> avg); normally, the infix function > takes two parameters of the same type, and returns a Bool - by wrapping in parenthesis and providing an expression on one side, I have partially applied it, which allows it to be used as a filter function
The where keyword. I used this to clean it all up a little and make it more readable.
The filter function, which I mentioned above.
Function application using $. This operator just changes the function application from left-associative to right-associative.
There are a number of problems here:
length doesn't do what you want it to. length returns the length of a list, and there are no lists in your howManyAvergageThree
averageThree returns a Float. howManyAverageThree needs to account for that. Specifically, > needs its arguments to be of the same type.
The call to averageThree in the second function needs some arguments.
Here's a working version:
howManyAverageThree x y z = length [ i | i <- [x, y, z], fromIntegral i > avg]
where avg = averageThree x y z
I have a graph like this:
As part of a homework assignment I want to find the triangle (1->2->5). I have no idea how to find this.
In my case, I defined my graph:
type Graph = (Int, Int -> Int -> Bool)
g 2 3 = True
g 3 2 = True
g 1 2 = True
g 2 1 = True
g 1 1 = True
g n m = False
Answer to 2 comment.
I did this and it works, I think.
triangles :: [(Int, Int, Int)]
triangles = [(x, y, z) | x <- [1..3], y <- [1..x], z <- [1..y], isTriangle (x, y, z)]
isTriangle :: (Int, Int, Int) -> Bool
isTriangle (x, y, z) = g x y && g y z && g x z
I removed (_,g) and (n,g) (I dont understand why we need them :)
I call trinagles and it return (1,1,1) (2,1,1) (in my case). Is it right?
I guess the first Int of Graph is a bound for your nodes (like, 6 if the nodes are in [1..6]).
Therefore, you would like a function that returns the triangles of a graph, so the type might be:
triangles :: Graph -> [(Int, Int, Int)]
Now, a triangle exists whenever, for 3 nodes, say x y and z, all the combinations return True through g.
So, you might want to consider generating all these combinations (possibly avoiding the ones that are equivalent via re-ordering), and filter out only those that validate the criterion:
isTriangle :: Graph -> (Int, Int, Int) -> Bool
isTriangle (_, g) (x, y, z) == g x y && g y z && g x z
For this, you could use a list comprehension, or the function filter which has type (a -> Bool) -> [a] -> [a]
Answer to your first comment:
First, you would need to implement the triangles function, which is the reason of the error. But, as you have done in test, you could simply generate these triangles on the fly.
Now, you wrote:
test = filter (isTriangle) [(x,y,z) | x <- [1..3], y <- [1..3], z <- [1..3]]
Two things about this:
First, you wouldn't need the parentheses around isTriangle for what you wrote, but it is incorrect, since isTriangle expects a graph as its first parameter
Second, you are going to obtain a lot of duplicates, and if you want, you can prevent this by not generating them in the first place:
test = filter (isTriangle) [(x,y,z) | x <- [1..3], y <- [1..x], z <- [1..y]]
Alternatively, you can dismiss the filter function by providing a guard in the list comprehension syntax, as this:
[(x, y, z) | x <- [1..3], y <- [1..x], z <- [1..y], isTriangle yourGraph (x, y, z)]
Now, I'll let you go on with the details. You will want to make this a function that takes a graph, and to replace this 3 by the number of nodes in the graph, and yourGraph by said graph.
Since you chose to use list comprehension, forget about the generating function that I wrote about earlier, its purpose was just to generate input for filter, but with the list comprehension approach you won't necessarily need it.
Answer to your second comment:
You want to write a function:
triangles :: Graph -> [(Int, Int, Int)]
triangles (n, g) = [(x, y, z) | ...]
The ... are to be replaced with the correct things, from earlier (ranges for x, y and z, as well as the predicate isTriangle).
Alternatively, you can cut this in two functions:
allTriangles :: Int -> [(Int, Int, Int)]
allTriangles n = [(x, y, z) | ...]
graphTriangles :: Graph -> [(Int, Int, Int)]
graphTriangles (n, g) = [t | t <- allTriangles n, isGraphTriangle t]
where isGraphTriangle (x, y, z) = ...
This way, you could potentially reuse allTriangles for something else. If you don't feel the need, you can stay with the one-shot big comprehension triangles, since it's a homework you probably won't build up on it.
I try not to fill all the ... so that you can do it yourself and hopefully understand :)
Correcting your solution:
First, my mistake on the ranges, it should be x <- [1..n], y <- [x+1..n], z <- [y+1..n] where n denotes the number of nodes in your graph. This way, you only capture triples where x < y < z, which ensures that you only see one occurence of each set of three points.
Second, the reason why I put the graph as a parameter to the functions is that you might want to reuse the same function for another graph. By hardcoding g and 6 in your functions, you make them really specific to the particular graph you described, but if you want to compute triangles on a certain number of graphs, you do not want to write one function per graph!
I don’t really like your graph type but whatever. Here’s the algorithm we will use:
First find a Node x of the graph.
For every other node y see if it connects to x
If y does connect to x then for each node z, see if it connects to x and y
If so then return it.
To avoid duplicates, we require z<x<y
nodes (n,_) = [1..n]
nodesBefore (n,_) k = [1..min n (k - 1)]
edge (_,e) x y = e x y
neighboursBefore g x = [ y | y <- nodesBefore g x, edge g x y]
triangles g = [(x,y,z) | x <- nodes g, y <- neighboursBefore g x, z <- neighboursBefore g y, edge g x z]