I made a way to get more free stuff and free stuff is good.
The current implementation of deriveVia
is here, it works with all the examples here. Needs GHC 8.2 and th-desugar.
for new Haskellers to get pampered by their compiler. For the price of a line or two the compiler offers to do your job, to write uninteresting code for you (in the form of type classes) such as equality, comparison, serialization, ... in the case of 3-D vectors
-- Eq :: Type -> Constraint
-- Ord :: Type -> Constraint
-- Show :: Type -> Constraint
-- Read :: Type -> Constraint
data V3 a = V3 a a a
deriving (Eq, Ord, Show, Read, ...)
In the distant past GHC could only be cajoled into defining a few classes hard-coded into the compiler. With time that list grew to include more interesting classes — type classes over type constructors (of kind Type -> Type
) rather than simple types (Type
) — but always at the discretion of compiler writers.
{-# Language DeriveTraversable #-}
-- Functor :: (Type -> Type) -> Constraint
-- Foldable :: (Type -> Type) -> Constraint
-- Traversable :: (Type -> Type) -> Constraint
data V3 a = V3 a a a
deriving (..., Functor, Foldable, Traversable)
With the advent of default methods and Generic
the rubber band was on the other claw, library writers could now specify a generic, singular (privileged) function to be the default implementation of certain methods.
The JSON-library aeson provides default implementations of JSON serialization
class ToJSON a where
toJSON :: a -> Value
toJSON = genericToJSON defaultOptions
default
toJSON :: (Generic a, GToJSON Value Zero (Rep a)) => a -> Value
class FromJSON a where
parseJSON :: Value -> Parser a
parseJSON = genericParseJSON defaultOptions
default
parseJSON :: (Generic a, GFromJSON Zero (Rep a)) => Value -> Parser a
so users don't even have to specify them
{-# Language DeriveGeneric #-}
import GHC.Generics (Generic)
import Data.Aeson (ToJSON, FromJSON)
data V3 a = V3 a a a
deriving
(..., Generic)
instance ToJSON a => ToJSON (V3 a)
instance FromJSON a => FromJSON (V3 a)
Then we got the option of deriving any class like this
{-# Language ..., DeriveAnyClass #-}
data V3 a = V3 a a a
deriving
(..., Generic, ToJSON, FromJSON)
and with the latest release (GHC 8.2) we get the option to be more explicit
{-# Language ..., DerivingStrategies #-}
data V3 a = V3 a a a
deriving
(Eq, Ord, Show, Read, Generic)
deriving
(Functor, Foldable, Traversable)
deriving anyclass
(ToJSON, FromJSON)
Spoilers
Assuming an
Applicative V3
instance we can make it into a numberwith my solution we can define a newtype
WrappedApplicative
and write those instances once and for all.. and then use that newtype to derive them for anyApplicative
(the applicative-numbers package provides an include file.. not great folks)This gets translated into safe coercions
With a tiny bit of compiler support it can be written