Is there any way to constrain type parameters in a typeclass from an external library?

173 Views Asked by At

I continually trick myself into thinking it'd be possible to somehow (at least imitate) having a typeclass, say, from base be arbitrarily constrained

(For all my searching I haven't found anything that satisfyingly addresses constraining type params from external libraries).


TL;DR How can I write the Arrow instance, even if I need to change MyArr, but must retain Typeable on its values?:

data MyArr a b where
  Arr :: (Typeable a, Typeable b) => (a -> b) -> MyArr a b

instance Arrow MyArr where ???

Consider this definition of Arrows:

class Arrow p where
  arr :: (a -> b) -> p a b

Sometimes I reeeeally wish it were

class Arrow p where
  arr :: (Typeable a, Typeable b) => ...

I would like to have that for the GADT I mentioned above; where my constructor carries a proof of its params Typeableity:

data MyArr a b where
  Arr :: (Typeable a, Typeable b) => (a -> b) -> MyArr a b

I cannot directly write an Arrow instance for that, because arr must be forall a b., and cannot generically conjure a proof of Typeable a. I think this is the crux of the problem.

If I could write my own class Arrow, I could make it work with ConstraintKinds using a kind family:

class Arrow p where
  type ArrowC p :: * -> Constraint
  arr :: (ArrowC p a, ArrowC p b) => ...

But since I'd like to remain compatible with proc notation, and other libraries, I cannot do that. So I keep thinking I could somehow define my Arrow's datatypes taking advantage of ConstraintKinds, or constraints, or, reify and reflection

data MyArr a b where
  Arr :: Dict (Typeable a) -> Dict (Typeable b) -> (a -> b) -> MyArr a b

But what Dict can I pass into the instance's definition of arr? or perhaps

data MyArr (k :: * -> Constraint) a b where
  Arr :: (k a, k b) => (a -> b) -> MyArr k a b

But dangit, that doesn't work either, because again, arr's a and b must be unconstrained

I've attempted tricks with having singleton values carry proofs, or constrain a and b by TypeFamilies, but alas, to no avail.

One of these options MUST be possible, right?

I have twisted myself in a ball of confusion that for months, I keep revisiting this problem, and tricking myself into thinking it's possible.

0

There are 0 best solutions below