Reputation: 2152
I had some types like this:
data Currency = USD | EUR
deriving (Show, Typeable)
data Money :: Currency -> * where
Money :: Int -> Money c
deriving (Show, Typeable)
And I wanted to use typeOf
with them in this function:
findRate :: Money a -> Rates -> Maybe Double
findRate a = M.lookup (typeOf a)
That didn't work, because the type a
in findRate didn't have a Typeable
instance. So I fixed it by doing this:
deriving instance Typeable USD
deriving instance Typeable EUR
findRate :: (Typeable a) => Money a -> Rates -> Maybe Double
However, that becomes a lot of boilerplate when the number of currencies increase. Is there a way to specify that all types of kind Currency
should derive a Typeable
instance?
EDIT: Also, a way to make it infer that in Money a
the a
is Typeable
would be nice, so then I don't need to add (Typeable a) =>
everywhere. That's minor though.
Upvotes: 3
Views: 663
Reputation: 908
If you're tracking an older document that requires Typeable, you likely do not need it. As of ghc 8.2, the explicit call for Typeable is deprecated and included "par for the course"; so no language pragma etc. is required.
Upvotes: 1
Reputation: 18189
Yes, you can use the AutoDeriveTypeable
extension.
For the other part, the closest thing I could think of was to put Typeable c =>
inside the GADT definition as follows:
{-# LANGUAGE AutoDeriveTypeable #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
import Data.Typeable
import qualified Data.Map as M
type Rates = M.Map TypeRep Double
data Currency = USD | EUR
deriving (Show, Typeable)
data Money :: Currency -> * where
Money :: Typeable c => Int -> Money c
instance Show (Money c) where
show (Money n) = "Money " ++ show n
findRate :: Money a -> Rates -> Maybe Double
findRate a@(Money _) = M.lookup (typeOf a)
Note though:
a
to get the Typeable
context out of it, which typeOf
itself doesn't.Show
automatically for the GADT.Upvotes: 4