Search code examples
haskellpolymorphismcoercion

Coerce to multiple-parameter type in Haskell


I have a type

class IntegerAsType a where
  value :: a -> Integer

data T5
instance IntegerAsType T5 where value _ = 5

newtype (Num a, IntegerAsType n) => PolyRing a n = PolyRing [a]

My main question is: how do I define a variable in a particular PolyRing?

It should be something like:

x = [1, 2, 3] :: Integer T5

(I think) The question is: what is the correct syntax after the ::?

I'm getting the error

Couldn't match expected type `PolyRing Integer T5'
         with actual type `[t0]'
In the expression: [1, 2, 3] :: PolyRing Integer T5
In an equation for `x': x = [1, 2, 3] :: PolyRing Integer T5

Also, I'm looking for a better way to implement this. In particular, I'd really like for the type a to be inferred from the type of list elements, while the IntegerAsType n must be specified (it shouldn't depend on the length of the list, even if that is possible).

Things I've tried so far:

x = [1,2,3] :: PolyRing (Integer, T5)

x = [1,2,3] :: PolyRing Integer T5

Solution

  • First Note

    Data type contexts, such as:

    newtype (Num a, IntegerAsType n) => PolyRing a n = PolyRing [a]
    

    are generally a bad idea and have been retired from the language.

    Ignoring That

    To construct an instance you must use the data constructor PolyRing:

    PolyRing [1,2,3]
    

    But that isn't enough, the type inference so far will be (IntegerAsType n) => PolyRing Integer n. Your final type signature would finish this up let x = PolyRing [1,2,3] :: PolyRing Integer T5.

    Returning To the First Note

    Still, perhaps you wanted:

    newtype PolyRing a n = PolyRing [a]
    

    And every function that builds or consumes a polyring can enforce the needed constraints:

    func :: (Num a, IntegerAsType n) => PolyRing a n -> ...