Data Constructor taking any Numeric type as an argument

Viewed 75

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
2 Answers

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.

Related