Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does deriving do/mean in Haskell?

The definition of deriving on stack overflow is:

"In Haskell, a derived instance is an instance declaration that is generated automatically in conjunction with a data or newtype declaration. The body of a derived instance declaration is derived syntactically from the definition of the associated type."

I don't really understand any of it to be honest.

The code below is taken from: Link

data BaseballPlayer = Pitcher 
                        | Catcher
                        | Infielder
                        | Outfielder
                        deriving Show

barryBonds :: BaseballPlayer -> Bool
barryBonds Outfielder = True

barryInOf = print(barryBonds Outfielder)

My question is, what does the deriving-statement do in this specific case, and also what does the deriving-statement do in general?.

like image 381
August Jelemson Avatar asked Jun 25 '17 09:06

August Jelemson


People also ask

What is a Typeclass in Haskell?

What's a typeclass in Haskell? A typeclass defines a set of methods that is shared across multiple types. For a type to belong to a typeclass, it needs to implement the methods of that typeclass. These implementations are ad-hoc: methods can have different implementations for different types.

What is EQ Haskell?

The Eq typeclass provides an interface for testing for equality. Any type where it makes sense to test for equality between two values of that type should be a member of the Eq class. All standard Haskell types except for IO (the type for dealing with input and output) and functions are a part of the Eq typeclass.

What is show in Haskell?

The shows functions return a function that prepends the output String to an existing String . This allows constant-time concatenation of results using function composition.

What is instance Haskell?

An instance of a class is an individual object which belongs to that class. In Haskell, the class system is (roughly speaking) a way to group similar types. (This is the reason we call them "type classes"). An instance of a class is an individual type which belongs to that class.


1 Answers

In short:

deriving automatically implements functions for a few of Haskell's typeclasses such as Show and Eq. This cannot be done with arbitrary typeclasses, but the ones for which deriving does work for are simple enough for automatic implementation.

The Show typeclass defines functions for how to represent data types as a String.

More extensively:

Are you familiar with typeclasses?

https://www.haskell.org/tutorial/classes.html

Typeclasses are similar to interfaces in Java: they define a few functions that any data type who wants to use those functions can implement.

For instance, say we have a class like such:

class Comparable a where
    lessThan :: a -> a -> Bool
    equalsTo :: a -> a -> Bool

Beware of the word class. It means typeclass in the Haskell setting, not a typical "class" you would hear about in object oriented languages. The a here is a filler type, similar to how you would expect templates would work in C++ and generics to behave in Java.

Let's say we define a data type as follows:

data Color = Red | Green | Blue

To make Comparable work with Color, we implement an instance of Comparable:

instance Comparable Color where
    lessThan Red   Green = True
    lessThan Red   Blue  = True
    lessThan Green Blue  = True
    lessThan _     _     = False

    equalsTo Red   Red   = True
    equalsTo Green Green = True
    equalsTo Blue  Blue  = True
    equalsTo _     _     = False

Roughly speaking, this now allows you to "compare" Red, Green, and Blue with each other. But was there any way that GHC could have automagically guessed that this is was the exact "order" you wanted?

Taking a step back, the typeclass Show has a similar structure:

https://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Show.html#Show

class  Show a  where
    showsPrec :: Int -> a -> ShowS
    show      :: a   -> String
    showList  :: [a] -> ShowS

    showsPrec _ x s = show x ++ s
    show x          = shows x ""
    showList ls   s = showList__ shows ls s

Something to notice is that functions within a typeclass may be defined in terms of each other. Indeed, we could have also easily done:

class Comparable a where
    lessThan :: a -> a -> Bool
    equalsTo :: a -> a -> Bool

    greaterThan :: a -> a -> Bool
    greaterThan lhs rhs = not (lessThan lhs rhs && equalsTo lhs rhs)

However, the key point is this: for arbitrary user-defined typeclasses, GHC has no idea how their functions should be implemented when you try to associate the typeclass with a data type such as Color or BaseballPlayer. For some typeclasses such as Show, Eq, Ord, etc, where the functionality is simple enough, GHC can generate default implementations that you can of course overwrite yourself.

Indeed, let's experiment by trying to compile the following:

data Color = Red | Green | Blue deriving (Comparable)

The result I get is this:

test.hs:9:43:
    Can't make a derived instance of ‘Comparable Color’:
      ‘Comparable’ is not a derivable class
      Try enabling DeriveAnyClass
    In the data declaration for ‘Color’

Of course, some GHC extensions can be used to extend the power of deriving, but that's for another day :)

like image 120
Anton Xue Avatar answered Sep 28 '22 14:09

Anton Xue