Reputation: 79368
I am just beginning to learn Haskell. I have seen many intro examples explaining the basics of types, but they often have a deriving
statement below the type. Here is an example from Chapter 3 of RealWorldHaskell:
data Cartesian2D = Cartesian2D Double Double
deriving (Eq, Show)
data Polar2D = Polar2D Double Double
deriving (Eq, Show)
They explain deriving somewhat in Chapter 6, which helps you know how it is used.
So far from what I understand, deriving (Show)
is necessary to tell Haskell how to turn your type into a string. That makes sense at a practical level. I come from JavaScript land, so to me you could easily imagine this would be implemented like:
Polar2D.prototype.toString = function(){
return '[Polar2D]';
};
In Haskell, they give the example of how to implement your own Show
for the Color
type, instead of using deriving
.
data Color = Red | Green | Blue
instance Show Color where
Red = "red"
Green = "green"
Blue = "blue"
That means when your in the ghci
repl, you can do:
> show Red
"red"
But this doesn't explain what deriving
is actually doing, it's still magic to me.
My question is, what is happening under the hood with deriving
? Also, is there a place on GitHub in the Haskell source where you can see the implementation? That may also be helpful.
Upvotes: 14
Views: 348
Reputation: 8419
GHC is effectively just writing the same instance you wrote by hand, if you pass -ddump-deriv
to the compiler you can see the code it generates. For instance:
Prelude> data Color = Red | Green | Blue deriving (Show)
==================== Derived instances ====================
Derived instances:
instance Show Color where
showsPrec _ Red = showString "Red"
showsPrec _ Green = showString "Green"
showsPrec _ Blue = showString "Blue"
showList = showList__ (showsPrec 0)
Generic representation:
Generated datatypes for meta-information:
Representation types:
There's not really much magic going on here, Show
just has a very mechanical implementation. Inside it looks at the internal form of the data constructors (the type is DataConRep
in GHC's source ) which it gets from translating the frontend AST and then looks at the names provided in the frontend source and adds a new Show instance in terms of these names and any nested types that also implement Show. The new auto-generated typeclass is registered just like a hand-coded class as if it were written in the current module.
Upvotes: 16