1

I trying to create a type class Place which has String Coord [Int] , and a testData to store all the element into a list

data Place =  Place String Coord [Int]
             deriving (Ord,Eq,Show,Read)

data Coord = Cord Double Double
             deriving (Ord ,Eq ,Show ,Read)


testData :: [Place]
testData = [  "London"       Cord(51.5  ,-0.1)   0, 0, 5, 8, 8, 0, 0 
              "Cardiff"      Cord(51.5  ,-3.2)   12, 8, 15, 0, 0, 0, 2
              "Norwich"      Cord(52.6  , 1.3)   0, 6, 5, 0, 0, 0, 3 
              "Birmingham"   Cord(52.5  ,-1.9)   0, 2, 10, 7, 8, 2, 2
              "Liverpool"    Cord(53.4  ,-3.0)   8, 16, 20, 3, 4, 9, 2
              "Hull"         Cord(53.8  ,-0.3)   0, 6, 5, 0, 0, 0, 4
              "Newcastle"    Cord(55.0  ,-1.6)   0, 0, 8, 3, 6, 7, 5
              "Belfast"      Cord(54.6  ,-5.9)   10, 18, 14, 0, 6, 5, 2
              "Glasgow"      Cord(55.9  ,-4.3)   7, 5, 3, 0, 6, 5, 0
              "Plymouth"     Cord(50.4  ,-4.1)   4, 9, 0, 0, 0, 6, 5
              "Aberdeen"     Cord(57.1  ,-2.1)   0, 0, 6, 5, 8, 2, 0
              "Stornoway"    Cord(58.2  ,-6.4)   15, 6, 15, 0, 0, 4, 2
              "Lerwick"      Cord(60.2  ,-1.1)   8, 10, 5, 5, 0, 0, 3
              "St Helier"    Cord(49.2  ,-2.1)     0, 0, 0, 0, 6, 10, 0 ]

But it keep giving me this error

UP917725.hs:20:15: error:
    • Couldn't match expected type ‘(Double -> Double -> Coord)
                                    -> (Double, Double) -> Integer -> Place’
                  with actual type ‘[Char]’
    • The function ‘"London"’ is applied to three arguments,
      but its type ‘[Char]’ has none
      In the expression: "London" Cord (51.5, - 0.1) 0
      In the expression: ["London" Cord (51.5, - 0.1) 0, 0, 5, 8, ....]
   |
20 | testData = [  "London"       Cord(51.5  ,-0.1)   0, 0, 5, 8, 8, 0, 0     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

It keep saying that the actual type is Char, I also tried putting parenthesis with the int list aswell , So I probably think the error is somewhere around the definition of the datatype

2
  • 4
    Welcome to SO! What is going on with all these posts about the exact same exercise of this one haskell course at portsmouth uni? Commented Apr 21, 2020 at 11:53
  • Cord(x,y) should be (Cord x y) in your definition of testData. The data constructor has kind Double -> Double -> Coord, not (Double, Double) -> Coord. Commented Apr 21, 2020 at 13:00

2 Answers 2

4

Your datatype definition is perfectly fine, you are just missing the Place data constructor in your list. Also function application has a different syntax in Haskell. Instead of Cord(53.8, -0.3) you have to use Cord 53.8 (-0.3).

For example:

testData :: [Place]
testData = [ Place "London" (Cord 51.5 (-0.1)) [0, 0, 5, 8, 8, 0, 0]
           , Place "Cardiff" (Cord 51.5 (-3.2)) [12, 8, 15, 0, 0, 0, 2]
           -- etc.
           ]
Sign up to request clarification or add additional context in comments.

Comments

2

Let's reduce this to the minimal list that has the same problem:

testData = [  "London"       Cord(51.5  ,-0.1)   0, 0, 5, 8, 8, 0, 0 
              "Cardiff"      Cord(51.5  ,-3.2)   12, 8, 15, 0, 0, 0, 2 ]

First note that though Haskell does have indentation sensitivity, the line break does not mean anything here. This is actually parsed as

testData = [  ("London"       Cord(51.5  ,-0.1)   0), 0, 5, 8, 8, 0, (0 
               "Cardiff"      Cord(51.5  ,-3.2)   12), 8, 15, 0, 0, 0, 2 ]

or

testData = [ "London" Cord (51.5,-0.1) 0
           , 0
           ‥‥
           , 0
           , 0 "Cardiff" Cord (51.5,-3.2) 12
           , 8
           ‥‥ 
           , 2 
           ]

i.e. the separators of list elements are completely different from what you intended. To get that each city is an entry, put the commas between them and and ensure that any finer-lever commas are encapsulated in parens – in doubt, by putting each list entry entirely in a paren:

testData = [ ("London"       Cord(51.5  ,-0.1)   0, 0, 5, 8, 8, 0, 0)
           , ("Cardiff"      Cord(51.5  ,-3.2)   12, 8, 15, 0, 0, 0, 2) ]

Now, by simply having commas in parens you make these list entries tuples. That's not what you want, but let's go for it for now...

The first tuple entry would be

   "London" Cord(51.5  ,-0.1) 0

Again, whitespace doesn't really affect parsing; this is the same as

   "London" (Cord) (51.5,-0.1) (0)

which would mean, you apply the function "London" to the arguments Coord, then (51.5,-0.1), then 0. How can "London" possibly be a function?

No, what you want is have "London" as the first data field of a Place value. Place is a tuple-ish type, but it's not literally a tuple: to generate a Place value out of the desired data-field values, you need to use its constructor, which also happens to be called Place. (It's common in Haskell to give constructors the same name as the type they construct, but it could just as well be called different.) So that would be

     Place "London" Cord(51.5  ,-0.1) 0

Still not right: Cord and (51.5,-0.1) are separate here regardless of whether you have whitespace between them, so this would be parsed

     Place ("London") (Cord) (51.5  ,-0.1) (0)

Instead you want

     Place "London" (Cord (51.5  ,-0.1)) 0

We're almost done. Only, that 0 wasn't actually supposed to be provided on its own: what you want there is a list of ints, of which 0 was only the head.

Well, solution is to put all those list-entry numbers in brackets, specifically list-brackets:

     Place "London" (Cord (51.5  ,-0.1)) [0, 0, 5, 8, 8, 0, 0]

Then, one last thing: Coord is also a constructor, taking floating-point numbers. But you give it a single tuple of such numbers. So instead of Cord (51.5,-0.1), you want Cord 51.5 (-0.1).

1 Comment

You should update to call Cord correctly; the OP's usage doesn't match its defined type.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.