
Hello Brandon,
This could be handled with existential wrappers, except that the wrapping is annoying, and probably interferes with optimizing when a concrete type is known. Instead, a few changes to type synonyms handle Bulat's cases.
With the proper interpretation, type synonyms like type ABlockStream = BlockStream b => b type AMemoryStream = MemoryStream m => m
support some of Bulat's signatures like copyStream :: ABlockStream -> ABlockStream -> Integer -> IO () saveToFile :: AMemoryStream -> FilePath -> IO ()
This requires two changes to the interpretation of type synonyms
1) Free variables in the definition of the type synonym are allowed, and become fresh (wobbly) variables when the synonym is applied
2) Class constraints in the definition of a type synonym float up to the closest binding of a constrained type.
I find those free variables a bit scary. It is not clear to me what it means for a value to have type 'AnAuto'. I like to think about type synonyms as only that, synonyms - so you can always substitute the definition for an occurrence. How does your proposal compare to introducing existential types proper? As in type ABlockStream = exists b. BlockStream b => b . This is a known extension, supported partly by jhc and fully by ehc. It seems to be exactly what you need for
copyStream :: ABlockStream -> ABlockStream -> Integer -> IO ()
Greetings, Arie -- Mr. Pelican Shit may be Willy. ^ /e\ ---