Filipe
Filipe

Reputation: 35

Beginner to haskell

   ver :: (Float,Float)->(Float,Float)->(Float,Float)->(Float,Float,Float)
   ver g=sqrt((((fst x -fst y)^2)+((snd x -snd y)^2))) 
   ver g1=sqrt((((fst x -fst z)^2)+((snd x -snd z)^2))) 
   ver g2=sqrt((((fst y -fst z)^2)+((snd y -snd z)^2)))
   ():g++g1++g2

I write this and I keep getting the error: naked expression at top level

What I want to do is to take the distance between 3 buildings and present them as a tuple for exemple: (dAB,dBC,dAC)

Upvotes: 0

Views: 168

Answers (4)

MdxBhmt
MdxBhmt

Reputation: 1310

Before I start listing what's wrong with your code and how to fix it, I recommend reading some tutorial or haskell introdutory text first, like Learn You a Haskell for Great Good, since your code show that you're not grasping some basic syntax.

First, the error you get comes from

 ():g++g1++g2

In haskell, whatever is in the top level (0 indentation) must be part of a declaration of some sort(imports, type signature) or how implementation of a function.

So you have an implementation of something (albeit wrong, but more on that later), but ask yourself, "How I know this line is related to ver?" Well, in haskell you have special keywords like let or where to express this. Since you have none of those, that line of code is lost, not pertaining to an implementation and it cannot exist at top level - thus leading to the error. I'll show how to fix that soon.

Second, that line doesn't do what you expect. () represent an empty tuple, : is a list constructor and ++ is list append. Neither makes sense in order to create a tuple of floats^3

You need something as:

(,,) g g1 g2 
--or
(g,g1,g2)

Third, your function implementation is unrelated to what the type specifies. That is, you have 3 versions of ver in place of one ver with 3 arguments. Ask yourself again,"How do I know where x y z comes from"?

If you want to define a function with 3 arguments this is how the function should look like:

ver x y z = -- Insert the calculations you want.

See? x y z are input variables for your function. Whatever you put on the left side of = is an input, whatever comes from the right side, is the output.

Ok, but how about g g1 g2? How can I tell that I want to calculate those 3 values, give them a name, and then use them?

It's time to use that where clause I told you before. Look at how your function should look like:

ver :: (Float,Float)->(Float,Float)->(Float,Float)->(Float,Float,Float)
ver x y z = (g,g1,g2)
     where g=sqrt((((fst x -fst y)^2)+((snd x -snd y)^2))) 
           g1=sqrt((((fst x -fst z)^2)+((snd x -snd z)^2))) 
           g2=sqrt((((fst y -fst z)^2)+((snd y -snd z)^2)))

And be sure to watch out for the indentation, since if you put where at the same level as ver, you are not expressing to which function that where belongs.

Upvotes: 1

Boris
Boris

Reputation: 5176

The problem is with the last line: ():g++g1++g2. That is the naked expression. At the top level of the file, you can only have definitions like ver g=sqrt((((fst x -fst y)^2)+((snd x -snd y)^2))) or type annotations like ver :: (Float,Float)->(Float,Float)->(Float,Float)->(Float,Float,Float). To get rid of the parse error, just delete that last line from the file.

However, after you get rid of the parse error, you will get another error about the type of ver not matching what you have said in the annotation. This is a very good argument for making explicit type annotations as you have done, since it makes it clear if there is a misunderstanding about what the code does. In your case it seems that you think the ver function takes it's arguements one line at a time, which is not correct. As it stands, the type of ver should be t -> Double. You can check this by commenting out the type annotation, loading the function in ghci and typing :t ver. This will give you the type as Haskell sees it.

I think the easiest way for you to move forward is if I give you a working example:

cityA = (3,4)
cityB = (1,2)
cityC = (6,3)

dist :: (Double, Double) -> (Double, Double) -> Double
dist city1 city2 = sqrt((fst city1 - fst city2)^2 + (snd city1 - snd city2)^2)

tripleDist :: (Double, Double) -> (Double, Double) -> (Double, Double) -> (Double, Double, Double)
tripleDist city1 city2 city3 = (d12, d13, d23)
    where d12 = dist city1 city2
          d13 = dist city1 city3
          d23 = dist city2 city3

dists = tripleDist cityA cityB cityC

I hope this helps.

Upvotes: 0

user2829425
user2829425

Reputation:

You mean

ver :: (Float,Float)->(Float,Float)->(Float,Float)->(Float,Float,Float)
ver x y z = (g,g1,g2) where
   g=sqrt((((fst x -fst y)^2)+((snd x -snd y)^2))) 
   g1=sqrt((((fst x -fst z)^2)+((snd x -snd z)^2))) 
   g2=sqrt((((fst y -fst z)^2)+((snd y -snd z)^2)))

which compiles and gives

> ver (1,1) (4,-3) (8,0)
(5.0,7.071068,5.0)

...the triple (3-tuple) of distances between pairs of the three points given as arguments.

The "naked expression" error means you had something on a line which wasn't a function - your last line. Instead I've used where to introduce your intermediate calculations, but I could just as well have used let ... in ...:

ver' :: (Float,Float)->(Float,Float)->(Float,Float)->(Float,Float,Float)
ver' x y z = let
   g=sqrt((((fst x -fst y)^2)+((snd x -snd y)^2))) 
   g1=sqrt((((fst x -fst z)^2)+((snd x -snd z)^2))) 
   g2=sqrt((((fst y -fst z)^2)+((snd y -snd z)^2)))
     in (g,g1,g2)

The notation ():g++g1++g2 looks like you got a bit confused between tuples and lists. You can build lists up from the empty list, but you can't build tuples up.

For example, you can do 1:3:8:[] which is the same as [1,3,8], but you can't do 1:3:8:() because () is the empty tuple, not the empty list (a type error), and you can't do []:1:3:8 because 8 isn't a list, and : needs a list on the right of it. (This means you can add quickly to the front of the list, but not so quickly to the back.)

Maybe it's worth you working through a tutorial, answering all the exercises - you seem to have a conceptual picture of programming in Haskell that's short on practical details. I can recommend Learn You a Haskell for Great Good which is cheerily written, accessible, and you can read it for free online. Just remember to actually do all the exercises, and test your answers work! (Use ghci or hugs.) You'll learn faster with the regular testing and checking.

Upvotes: 3

AlanFoster
AlanFoster

Reputation: 8306

I believe you are wishing to pattern match all three tuples separately such as

type Location = (Float, Float)
ver :: Location -> Location -> Location -> (Float, Float, Float)
ver (aX, aY) (bX, bY) (cX, cY) = (0, 0, 0) {- Your logic -}

This will give you access to all three locations, IE x,y tuples.

As potentially a better way of dealing with this; You could rethink your function to transform an array of Location, and returning an array of distances for instance. This would allow you to write more elegant solution

Upvotes: 0

Related Questions