Function Overloading in Haskell

2020-07-13 04:26发布

问题:

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

回答1:

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)


回答2:

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.