consider snippet
{-# language scopedtypevariables #-} {-# language typefamilies #-} import data.proxy monadify' :: forall m sig. (monad m, sig sig) => proxy sig -> monadify m sig monadify' p = monadify p (return () :: m ()) type family monadify f monadify f (a -> r) = -> monadify f r monadify f = f class sig sig monadify :: monad m => proxy sig -> m () -> monadify m sig
i've given no instances, example usage f :: int -> string -> bool, monadify' f :: int -> string -> io bool
.
it fails typecheck following error message:
couldn't match expected type ‘monadify m sig’ actual type ‘monadify m0 sig0’ nb: ‘monadify’ type function, , may not injective type variables ‘m0’, ‘sig0’ ambiguous in ambiguity check type signature ‘monadify'’: monadify' :: forall (m :: * -> *) sig. (monad m, sig sig) => monadify m sig defer ambiguity check use sites, enable allowambiguoustypes in type signature ‘monadify'’: monadify' :: forall m sig. (monad m, sig sig) => monadify m sig
intuitively i'd should typecheck, ghc gets confused type family, not annotated injective (i'd rather not backwards compatibility). recover preimage m ()
, proxy
though, don't know what's problem here.
edit:
as error message suggests, throw in allowambiguoustypes
, in case fixes problems. don't know consequences of using extension, plus i'd rather know why example doesn't typecheck.
i have feeling has unifier first trying unify monadify m sig
s, thereby inferring can't prove sig
s , m
s identical. although unifier needed @ passed arguments know identical, might allowambiguoustypes
helps.
the problem monadify'
, not monadify
.
suppose calling
monadify' :: forall m sig. (monad m, sig sig) => monadify m sig
here there no proxies around so, without assuming monadify
injective, impossible compiler know m,sig
should instantiated to. needed understand instances (monad m, sig sig)
should used.
try instead working with
monadify' :: forall m sig. (monad m, sig sig) => proxy m -> proxy sig -> monadify m sig
also note monadify
not injective:
monadify ((->) bool) (io char) ~ bool -> io char monadify io (bool -> char) ~ bool -> io char
if use allowambiguoustypes
following not type check:
test :: forall m sig. (monad m, sig sig) => proxy sig -> proxy m -> monadify m sig test t _ = monadify' t -- type variable m0 ambiguous
we can fix passing explicit type argument m
:
test :: forall m sig. (monad m, sig sig) => proxy sig -> proxy m -> monadify m sig test t _ = monadify' @ m t
personally, i'd try remove proxies , use type arguments instead, since find cleaner, if requires ambiguous types.
Comments
Post a Comment