Is there any binder in haskell to introduce a type variable (and constraints) quantified in a type ?
I can add an extra argument, but it defeats the purpose.
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GADTs #-}
data Exists x = forall m. Monad m => Exists (m x)
convBad :: x -> Exists x
convBad x = Exists @m (return @m x, undefined) --Not in scope: type variable ‘m’typecheck
data Proxy (m:: * -> *) where Proxy :: Proxy m
convOk :: Monad m => x -> Proxy m -> Exists x
convOk x (_ :: Proxy m) = Exists (return @m x)
To bring type variables into scope, use
forall(enabled byExplicitForall, which is implied byScopedTypeVariables):But whether you do it like this or via
Proxy, keep in mind thatmmust be chosen at the point of creatingExists. So whoever calls theExistsconstructor must know whatmis.If you wanted it to be the other way around - i.e. whoever unwraps an
Existsvalue choosesm, - then yourforallshould be on the inside:Also, as @dfeuer points out in the comments, note that your original type definition (the one with
forallon the outside) is pretty much useless beyond just signifying the type ofx(same asProxydoes). This is because whoever consumes such value must be able to work with any monadm, and you can do anything with a monad unless you know what it is. You can't bind it insideIO, because it's not necessarilyIO, you can't pattern match it withJustorNothingbecause it's not necessarilyMaybe, and so on. The only thing you can do with it is bind it with>>=, but then you'll just get another instance of it, and you're back to square one.