error: Equations for ‘det’ have different numbers of arguments - haskell

I'm trying to calculate the determinant and I have the det function defined as below:
det :: (Double,Double) -> (Double,Double) -> Double
det _ = 0.0
det [] = error "its Empty!"
det [x] = error "contains only one point!"
det (x1, y1) (x2, y2) = (x1*y2 + x2*y1)
i get the following error
Equations for ‘det’ have different numbers of arguments
PolygonArea.hs:11:1-11
PolygonArea.hs:14:1-39
Failed, modules loaded: none.

First of all, the type (Double, Double) is always a pair of two Doubles, never an empty or a singleton list. Second, like the error message says, your cases for det need to have the same number of arguments, but one are given for the first three, and two for the fourth.
Fixing all these, you get
det :: (Double, Double) -> (Double, Double) -> Double
det (x1, y1) (x2, y2) = (x1 * y2 + x2 * y1)

Related

The constructor `Rectangle' should have 2 arguments, but has been given none

I have this code
type Point = (Int, Int)
data Points
= Rectangle Point Point
| Union Points Points
| Difference Points Points
inMax :: Int -> Int -> Int
inMax a b
| a < b = b
| otherwise = a
inMin :: Int -> Int -> Int
inMin a b
| a < b = a
| otherwise = b
inPoints :: Point -> Points -> Bool
inPoints (x, y) Rectangle (x1, y1) (x2, y2) = ((inMin x1 x2) <= x && x <= (inMax x1 x2)) && ((inMin y1 y2) <= y && y <= (inMax y1 y2))
I want to know if a point is in Rectangle but i got the next error: The constructor `Rectangle' should have 2 arguments, but has been given none. Why? How I should fix it?
In order to "unpack" the Rectangle, then you write Rectange between parenthesis:
inPoints :: Point -> Points -> Bool
inPoints (x, y) (Rectangle (x1, y1) (x2, y2)) = --- …
-- &uparrow; parenthesis &uparrow;
We thus perform pattern matching to obtain the points of the Rectangle. You can not use Rectange itself as a patern.
The expression inPoints (x, y) Rectangle (x1, y1) (x2, y2), no matter if it appears in a pattern left of the =, or right of it, parses as
(((inPoints (x,y))
Rectangle)
(x1,y1))
(x2,y2)
i.e. Rectangle is passed as an argument all by itself, and then (x1,x2) and (x2,y2) are passed as additional, separate arguments.
That's not completely absurd: in an expression, Rectange is just a function Point -> Point -> Points, and functions can be passed as function arguments just like any other values. For example you could define something like
unionBuilt :: (Point -> Point -> Points) -> [Point] -> Points
unionBuilt f (x₀:x₁:xs) = Union (f x₀ x₁) (unionBuilt xs)
unionBuilt f ... = ...
and that could then legitimately be called like
unionBuilt Rectangle [(1,2),(3,4)]
But in a pattern match, all constructors must be fully applied, i.e. if you pattern match on Rectangle then it must always come with two patterns for the containing points (even if you're not interested in them; then you need to use a blank pattern). This generally requires wrapping it in parentheses
So what you want is
inPoints (x,y) (Rectangle (x₁,y₁) (x₂,y₂)) = ...
Like most parentheses in Haskell expressions, these are only needed if the precedence rules don't already establish this way of parsing. In particular, if you had defined your function as an infix operator, then you would have been fine, and don't actually need any parentheses at all (except for the tuples):
(∈) :: Point -> Points -> Bool
(x, y) ∈ Rectangle (x₁, y₁) (x₂, y₂)
= inMin x₁ x₂ <= x && x <= inMax x₁ x₂
&& inMin y₁ y₂ <= y && y <= inMax y₁ y₂
This is because prefix function application, including constructors like Rectangle, always binds more tightly than infix operator application.

Trying to implement a function to create a linear space in Haskell but i'm getting a cast error

I'm trying to construct a function to create a linear space, similar to python.
Just to start the function I create this code:
lin x0 x1 tam zero
| tam - zero > 0.0 = (x0 + (x1-x0)/tam) : x1
| otherwise = x1
but i'm getting this error message:
<interactive>:2:45: error:
• Occurs check: cannot construct the infinite type: a ~ [a]
• In the second argument of ‘(:)’, namely ‘x1’
In the expression: (x0 + (x1 - x0) / tam) : x1
In an equation for ‘lin’:
lin x0 x1 tam zero
| tam - zero > 0 = (x0 + (x1 - x0) / tam) : x1
| otherwise = x1
• Relevant bindings include
zero :: a (bound at <interactive>:1:15)
tam :: a (bound at <interactive>:1:11)
x1 :: a (bound at <interactive>:1:8)
x0 :: a (bound at <interactive>:1:5)
lin :: a -> a -> a -> a -> [a] (bound at <interactive>:1:1)
what am I doing wrong? And how could I fix it?
Since you use x1 on the right of a :, x1 must be a list of some sort. However you are also using x1 on the left of the : as if it were a number. It can't be both and that is why you get the error message
In more detail, the compiler has figured out that x0, x1, tam, and zero all have the same type, which it calls a and that that is the type of (x0 + (x1 - x0) / tam). Since the operand on the left of the : has type a, x must have type [a]. But x1 also has type a and so the compiler tries to unify a with [a], which it can't do.
I assume the intention is that x0 and x1 are numbers, right? But : constructs a list out of a first element and another list containing the rest of the elements. So in
{- ... -} : x1
you are treating the number x1 as if it were a list. Similarly, since one branch of the conditional returns a list, the other branch must, too, and your
| otherwise = x1
is interpreted as trying to return x1 as if it were a list.
On the other hand, if the intention from the start was that x1 should be a list, then the computation
x0 + (x1 - x0)/tam
(or, more specifically, x1 - x0) doesn't really make sense, because it appears to treat x1 as a number instead of a list.

How to find an x y coordinate that is d distance away from a given point on slope m?

We are trying to define a Haskell function that gives the coordinates x, y given a starting point (x0, y0), distance from the starting coord, and slope of the line that goes through both points. Any ideas?
It will probably have a signature of
endPoint :: (Double, Double) -> double -> double -> (Double, Double)
How you would do this on paper is to use the distance formula (with the second point as variables/unknowns), which then gives you some ratio of the x and y for this new point, use that ratio as the substitution into the point-slope formula, which should give one of y and x, then plug that value into the formula again to get the x and y we don't have yet.
From this question, we can do the distance formula, but how do we deal with substitution? Is that possible in Haskell?
According to the definition of slope, this problem could be solved like this:
endPoint :: (Double, Double) -> Double -> Double -> (Double, Double)
endPoint (x0, y0) m d = (x0 + dx, y0 + dy)
where theta = atan m
dx = d * cos theta
dy = d * sin theta
Here is an example about point (2,8) and (3,20):
*Main> endPoint (2,8) 12 (sqrt $ 12 * 12 + 1)
(3.000000000000001,20.0)

Are the parentheses necessary in this Haskell code

data Point = Point Float Float deriving (Show)
data Line = Line Point Point deriving (Show)
onLine :: Line -> Point -> Bool
onLine (Line (Point x1 y1) (Point x2 y2)) (Point x y) = True
Is there a way not to use so many brackets ?
I recommend a tool called hlint for identifying places where you can simplify your code.
In your code /as written/, you're not using the values x1, y1, x2, y2, x or y, so you could just write:
onLine _ _ = True
However, I assume that's just a stub, and in reality you will do something with the variables. In general, if you really need to reference all those variables, then you need to write it the way you have done. However, maybe you're using a helper function that only needs the entire line value. Then you could write something like:
onLine l p = blah blah blah
-- use slope l and yIntercept l to figure out if p is on the line
slope :: Line -> Float
slope (Line (Point x1 y1) (Point x2 y2)) = (y2 - y1) / (x2 - x1)
yIntercept :: Line -> Float
yIntercept (Line (Point x1 y1) (Point x2 y2)) = blah blah blah
Alternatively, you can just use accessor functions to extract the x and y co-ordinates from points and lines, but in this case it will probably make your code messier.
Also, in Haskell I believe it's generally more efficient to use Double rather than Float.
You can sometimes avoid brackets with record notation, sometimes with $, sometimes with infix functions, and sometimes they're OK if not excessive.
Let's use record notation for points, which get heavy access for the coordinates, but we'll leave Line alone.
data Point = Point {x::Double,y::Double} deriving (Show)
data Line = Line Point Point deriving (Show)
This defines x :: Point -> Double and y :: Point -> Double.
There's no such thing as equality for floating points, but I'll go for roughly right:
accuracy = 0.000000000001
is :: Double -> Double -> Bool
is x y = abs (x - y) < accuracy
I can use this as x point1 `is` x point2 neatly avoiding the bracketed is (x point1) (x point2)
When your data structure is not so heavily nested with pattern matching, a few brackets are easy to read:
gradient :: Line -> Double
gradient (Line one two) = (y two - y one) / (x two - x one)
But we can go one level deeper without using excessive brackets because of the functions x and y.
asFunction :: Line -> (Double -> Double) -- ( ) for clarity, not necessity
asFunction l#(Line point _) = \xx -> gradient l * (xx - x point) + y point
Notice I've used l# to introduce an alias for (Line point _) to save typing on the right.
Now we can use the infix function trick to get rid of a few more brackets:
onLine :: Line -> Point -> Bool
onLine l p = l `asFunction` x p `is` y p
On the right hand side, you can use $ to get rid of brackets, but you can't use it on the left in pattern matching because it's a function f $ x = f x. For example
this (that (the other thing (something other)))
= this $ that $ the other thing $ something other
= this . that . the other thing $ something other
You can take the line and point apart within the function by defining accessors, but there is no way to do the pattern matching without the parentheses.
Another way of getting rid of the parentheses is to do the pattern matching in a number of case expressions:
onLine l p = case l of
Line p1 p2 -> case p1 of
Point x1 y1 -> case p2 of
Point x2 y2 -> case p of
Point x y -> True -- you can use x1,y1,x2,y2,x and y here
This is close to what the compiler 'translates' the patternmatches to, but of course this is not much of an improvement!
However, there are a number of ways of writing this expression that also translate to the same cascaded pattern matching; here's one:
onLine l p = let
Line (Point x1 y1) (Point x2 y2) = l
Point x y = p
in True
and here's another:
onLine l p = True where
Line (Point x1 y1) (Point x2 y2) = l
Point x y = p
The last one is pretty nice and readable, in my opinion, but the other suggestions are much better, since they'll lead to a better structured program!
(There's some stuff about irrefutable patterns that I'm glossing over, and this only works for single-constructor datatypes)

"Overloaded" value constructors

In "Making Our Own Types and Typeclasses" they give the following piece of code :
data Point = Point Float Float deriving (Show)
data Shape = Circle Point Float | Rectangle Point Point deriving (Show)
surface :: Shape -> Float
surface (Circle _ r) = pi * r ^ 2
surface (Rectangle (Point x1 y1) (Point x2 y2)) = (abs $ x2 - x1) * (abs $ y2 - y1)
nudge :: Shape -> Float -> Float -> Shape
nudge (Circle (Point x y) r) a b = Circle (Point (x+a) (y+b)) r
nudge (Rectangle (Point x1 y1) (Point x2 y2)) a b = Rectangle (Point (x1+a) (y1+b)) (Point (x2+a) (y2+b))
main = do
print (surface (Circle (Point 0 0) 24))
print (nudge (Circle (Point 34 34) 10) 5 10)
As it stands the pattern matching against constructors is getting quite cluttered at the point
nudge (Rectangle (Point x1 y1) (Point x2 y2)) a b = ....
Had we defined the Shape type as :
data Shape = Circle Point Float | Rectangle Float Float Float Float deriving (Show)
Then even though we lose a bit of clarity into the nature of the type, the patten matching looks less cluttered, as can be seen below :
data Point = Point Float Float deriving (Show)
data Shape = Circle Point Float | Rectangle Float Float Float Float deriving (Show)
surface :: Shape -> Float
surface (Circle _ r) = pi * r ^ 2
surface (Rectangle x1 y1 x2 y2) = (abs $ x2 - x1) * (abs $ y2 - y1)
nudge :: Shape -> Float -> Float -> Shape
nudge (Circle (Point x y) r) a b = Circle (Point (x+a) (y+b)) r
nudge (Rectangle x1 y1 x2 y2) a b = Rectangle (x1+a) (y1+b) (x2+a) (y2+b)
main = do
print (surface (Circle (Point 0 0) 24))
print (nudge (Circle (Point 34 34) 10) 5 10)
My question is whether it is possible to have both
Rectangle Point Point
and
Rectangle Float Float Float Float
in the same piece of code (i.e. a sort of "overloading" of value constructors), so that we can do something like :
...
surface (Rectangle (Point x1 y1) (Point x2 y2)) = (abs $ x2 - x1) * (abs $ y2 - y1)
...
nudge (Rectangle x1 y1 x2 y2) a b = Rectangle (x1+a) (y1+b) (x2+a) (y2+b)
where the "..." denotes the same as in the code above. Also are there any other tricks to make the notation a bit more compact at the "nudge (Rectangle...." point? Thanks
You could possibly use type classes to make a function behave as both Point -> Point -> Rectangle and Float -> Float -> Float -> Float -> Rectangle, but I wouldn't advocate it. It will be to much trouble for the gain. I don't think there's anyway you could make such an overloaded name usable in pattern matching anyway.
The way I see it, if you're only ever going to be using Point values by deconstructing them and operating on the raw Float values, then you're not really getting that much out of it, so you could resolve your problem by getting rid of it entirely.
But you're missing a golden opportunity to implement a function to adjust a point directly!
For starters I would make an Offset type to hold your a and b values. Then you make a function adjust :: Offset -> Point -> Point to do the combining. And then your nudge doesn't even need to understand the internal structure of a Point to do its job!
For example (Disclaimer: I haven't actually compiled this)1:
data Point = Point Float Float deriving (Show)
data Offset = Offset Float Float deriving (Show)
data Shape = Circle Point Float | Rectangle Point Point deriving (Show)
adjust :: Point -> Offset -> Point
adjust (Point x y) (Offset ox oy) = Point (x + ox) (y + oy)
nudge :: Shape -> Offset -> Shape
nudge (Circle c r) o = Circle (adjust c o) r
nudge (Rectangle p1 p2) o = Rectangle (adjust p1 o) (adjust p2 o)
And similarly there could be a whole family of operations on Point and Offset. For example offsetFrom :: Point -> Point -> Offset could be useful in your surface function. I once went overboard and used type classes to implement a family of operators (|+|, |*|, etc IIRC) which allowed various things to be combined (for example, you can add a Point and an Offset in either order to get a Point, you can add and subtract Offsets but not Points, you can multiply Offsets by scalars but not Points, etc). Not sure whether it was worth it in the end, but it made my code look like my maths a little more!
With your current code you're effectively implementing all operations on Point again every time you need them (including the same adjustment operation twice in the same equation in nudge, which is my take on why it looks quite so bad).
1 There's a certain argument to be made for making functions like adjust and nudge have signatures where the "main" thing being operated on comes last, so adjust :: Offset -> Point -> Point and nudge :: Offset -> Shape -> Shape. This can come in handy because then partially applying adjust gives you a "point transformer" with type Point -> Point, and similarly you can partially apply nudge to get a "shape transformer" with type Shape -> Shape.
This helps when you have a collection of points or shapes and you want to apply the same transformation to all of them, for example:
data Shape = Polygon [Point]
adjust :: Offset -> Point -> Point
adjust (Offset ox oy) (Point x y) = Point (x + ox) (y + oy)
nudge :: Offset -> Shape -> Shape
nudge o (Polygon ps) = Polygon (map (adjust o) ps)
And generally "transformers" with type Something -> Something are just useful things to have on your main data structures. So whenever you have a function that combines some auxiliary data with a Something to produce a new Something, it'll often turn out to be useful to put the Something as the last argument, so you have another easy source of transformer functions.
One option would be to use view patterns. Let me give you a short example:
{-# LANGUAGE ViewPatterns #-}
data Point = Point Float Float
data Shape = Circle Point Float | Rectangle Point Point
rectangleAsPoints :: Shape -> Maybe (Point,Point)
rectangleAsPoints (Rectangle a b) = Just (a,b)
rectangleAsPoints _ = Nothing
rectangleFromPoints :: Point -> Point -> Shape
rectangleFromPoints = Rectangle
rectangleAsCoords :: Shape -> Maybe (Float,Float,Float,Float)
rectangleAsCoords (Rectangle (Point x y) (Point a b)) = Just (x,y,a,b)
rectangleAsCoords _ = Nothing
rectangleFromCoords :: Float -> Float -> Float -> Float -> Shape
rectangleFromCoords a b c d = Rectangle (Point a b) (Point c d)
surface (rectangleAsPoints -> Just (Point x1 y1, Point x2 y2)) =
(abs $ x2 - x1) * (abs $ y2 - y1)
surface (Circle _ r) = pi * r ^ 2
nudge (rectangleAsCoords -> Just (x1,y1,x2,y2)) a b =
rectangleFromCoords (x1+a) (y1+b) (x2+a) (y2+b)
nudge (Circle (Point x y) r) a b = Circle (Point (x+a) (y+b)) r
For consistency's sake I implemented both views of rectangles as functions. This way the actual implementation of the Rectangle type can remain hidden.
Note how you can mix normal pattern matching and view patterns.
What you want is't possibile. For the purposes of pattern matching you could use ViewPatterns as a poor-mans replacement for multiple constructors and make a single function to ease construction:
{-# LANGUAGE ViewPatterns #-}
-- Your pattern match aid
unRectangle :: Shape -> Maybe (Float, Float, Float, Float)
unRectangle (Rectangle (Point x1 y1) (Point x2 y2)) = Just (x1,y1,x2,y2)
unRectangle _ = Nothing
-- your construction aid
rectangle :: Float -> Float -> Float -> Float -> Shape
rectangle x y u v = Rectangle (Point x y) (Point u v)
surface (unRectangle -> Just (x1,y1,x2,y2)) = (abs $ x2 - x1) * (abs $ y2 - y1)
...
nudge (unRectangle -> Just (x1,y1,x2,y2)) = rectangle (x1+a) (y1+b) (x2+a) (y2+b)

Resources