I was wondering if one could create a data constructor which instead of taking a specific type could take any of a given class.
So instead of
data Container = ContainerI Int | ContainerF Float
Something like
Container::(Num a)=>a
data Container = Container a
Not in standard Haskell. The normal way to achieve this is to leave Container fully generic, then require (Num a) => Container a in functions where it is important. The type checkers will prevent code which tries to use a Container with an unsupported type from compiling.
If you really want to be extra cautious about it you can keep the actual constructor off the export list an only provide functions that have (Num a) as an export, but that is usually not required.
As an example, look at Data.Set. The reality is that for Set a to work as intended you will need an Eq a instance. But that restriction is only required in functions that manipulate a Set, not the definition of Set a itself.
You can do what you're asking with an existentially-quantified data constructor, like this:
{-# LANGUAGE ExistentialQuantification #-}
data Container = forall a. Num a => Container a
But as John F. Miller's answer explains, this probably isn't what you actually want. Instead, just do data Container a = Container a and then declare functions like f :: Num a => Container a -> _whatever.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With