Brad
Brad

Reputation: 133

What is Haskell not happy about? It's complaining about my type signature

I've another issue with my Haskell. I'm given the following data constructor from a problem,

type Point = (Int, Int)

data Points = Lines Int Int
            | Columns Int Int
            | Union Points Points
            | Intersection Points Points

It's about points on a grid starting (0,0) and (x,y) has x as the horizontal distance from the origin and y as the vertical distance from the origin.

I tried to define a function "Lines" from this, which, given Lines x y would evaluate all points with vertical distance x ~ y on the grid. e.g.

> Lines 2 4 
(0,2)(1,2)(2,2)(3,2)....
(0,3)(1,3)(2,3)(3,3)....
(0,4)(1,4)(2,4)(3,4)....

and so on. Well what I did, was,

Lines :: Int -> Int -> Points
Lines lo hi = [ (_, y) | lo <= y && y <= hi ]

But Haskell complains that;

Invalid type signature Lines :: Int -> Int -> Points.
Should be of the form ::

what's this mean? "Points" is defined above already...surely "Int" "Points" are regarded as "types"? I don't see the problem, why is Haskell confused?

Upvotes: 1

Views: 1521

Answers (1)

MathematicalOrchid
MathematicalOrchid

Reputation: 62848

  1. Functions must not start with a capital letter. So you need to use lines, not Lines. This is probably the source of the error message you're seeing.

  2. The syntax [ ... ] is for creating a list of results, but your type signature claims that the function returns Points, which isn't any kind of list. If you meant to return a list of Point values, that's the [Point] type.

  3. I have literally no idea what your implementation of Lines is even trying to do. The syntax makes no sense to me.


OK, so taking your comments into account...

  • You can generate a list of numbers between lo and hi by writing [lo .. hi].

  • You say an "arbitrary" value can go in X, but you need to pin down exactly what that means. Your example seems to suggest you want the numbers from 0 upwards, forever. The way to generate that list is [0 .. ]. (Not giving an upper limit makes the list endless.)

  • Your example suggests you want a list of lists, with the inner list containing all points with the same Y-coordinate paired with all possible X-coordinates.

So here is one possible way to do that:

type Point = (Int, Int)

lines :: Int -> Int -> [[Point]]
lines lo hi = [ [(x,y) | x <- [0..]] | y <- [lo .. hi] ]

That's perhaps a teeny bit hard to read, with all those opening and closing brackets, so perhaps I can make it slightly cleaner:

lines lo hi =
  let
    xs = [0..]
    ys = [lo .. hi]
  in [    [(x,y) | x <- xs]    | y <- ys]

If you run this, you get

> lines 2 4
[[(0,2), (1,2), (2,2), ...],
[(0,3), (1,3), (2,3), ...],
[(0,4), (1,4), (2,4), ...]]

In other words, the outer list has 3 elements (Y=2, Y=3 and Y=4), and each of the three inner lists is infinitely long (every possible positive X value).

Upvotes: 9

Related Questions