Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function Overloading in Haskell

I have a structure which represents the equation of a line in the form m x + b and a structure of a point

Line { m :: Double, b :: Double } deriving( Show, Eq )
Point { x :: Double, y :: Double } deriving( Show, Eq )

I want the function perpendicular that does the following:

perpendicular (Line m b) (Point x y) = 
        Line m2 b2 where
                m2 = (-1/m)
                b2 = y - m2*x

if given a line and a point, or a partially applied Line

perpendicular (Line m b) = 
        Line m2 where
                m2 = (-1/m)

if only given a Line.

The problem here is that I get

Equations for `perpendicular' have different numbers of arguments

like image 285
Cristian Garcia Avatar asked May 26 '14 07:05

Cristian Garcia


People also ask

Does Haskell have function overloading?

Type classes in Haskell vs OO languages Type classes in Haskell are used to introduce overloaded functions.

Does Haskell have classes?

Haskell classes are roughly similar to a Java interface. Like an interface declaration, a Haskell class declaration defines a protocol for using an object rather than defining an object itself.


2 Answers

Haskell doesn't have function overloading in the sense you might be used to from imperative languages; I'm not even sure if type inference would still be decidable if that were allowed. The only kind of overloading you can get is with type classes, although that still doesn't allow you to define functions which take varying numbers of arguments.

Your case is a quite good example of why this can't work in haskell; If you have perpendicular someLine how is a haskell compiler supposed to figure out which of these functions you're talking about? Both would be valid in this situation, but the expression would have different types depending on which was picked.

like image 167
Cubic Avatar answered Sep 27 '22 03:09

Cubic


In the first case, you want the type of perpendicular to be Line -> Point -> Line, while in the second case you want it to have the type Line -> Double -> Line. This suggests that we can do this with a type class where we abstract over the type of the second argument:

class Perpendicular a where
  perpendicular :: Line -> a -> Line

Your first case then becomes an instance for Point

instance Perpendicular Point where
  perpendicular (Line m b) (Point x y) = Line m2 b2
    where m2 = (-1/m)
          b2 = y - m2*x

while the second becomes an instance for Double.

instance Perpendicular Double where
  perpendicular (Line m b) = Line m2
    where m2 = (-1/m)
like image 25
hammar Avatar answered Sep 25 '22 03:09

hammar