You can require the associated type to have a particular instance, like this:<br><br>class (Bar (Ret c)) =&gt; Cls c where<br>   type Ret c<br>   foo :: c -&gt; Ret c<br><br>Another option is to use existential types:<br><br>
data HasBar = forall a. Bar a =&gt; HasBar a<br><br>class Cls c where<br>    foo :: c -&gt; HasBar<br><br>You then have to wrap the result of &quot;foo&quot; by &quot;HasBar&quot;; then you can get the instance back out by case-matching on HasBar.  This is basically the same as Miguel&#39;s solution of returning a dictionary, except the dictionary is implicitly held in the existential instead of explicit.<br>
<br>  -- ryan<br><br><div class="gmail_quote">On Tue, Sep 29, 2009 at 10:25 PM, DNM <span dir="ltr">&lt;<a href="mailto:dnmehay@gmail.com">dnmehay@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
Dan, thanks again for the response.<br>
<br>
I changed my code to use type families to let each Cls instance (actually a<br>
more complicated instance in my code) determine which Bar instance type it<br>
will return, but this didn&#39;t seem to work.  The problem is that the client<br>
of the typeclass instance methds (&#39;useThisStuff&#39;, which calls on &#39;toNum&#39; and<br>
&#39;foo&#39; in the contrived example) expects some guarantee that (Ret c) is going<br>
to be an instance of Bar.  The actual client code I&#39;m using complains when<br>
it sees that the associated type doesn&#39;t guarantee that an instance of the<br>
appropriate class is instantiated.  I don&#39;t see any way to guarantee this<br>
without adding a context restriction in the class-level definition of Ret c,<br>
something like:<br>
<br>
class Cls c where<br>
   type Ret c :: (Bar *) =&gt; * -- or a better name<br>
   foo :: c -&gt; Ret c<br>
<br>
which isn&#39;t legal Haskell.  What I want to say is &quot;define Ret c however you<br>
want, but make sure it is an instance of Bar&quot; in the *class-level definition<br>
of Ret c*, so that any client of &#39;Cls&#39; will know that Ret c will be<br>
foo-able.<br>
<br>
Maybe I&#39;m missing some subtlety of type families...<br>
<br>
Any suggestions?<br>
<br>
--D.N.<br>
<div><div></div><div class="h5"><br>
<br>
Daniel Peebles wrote:<br>
&gt;<br>
&gt; In your class, you have:<br>
&gt;<br>
&gt; class Cls c where<br>
&gt;    foo :: (Bar b) =&gt; c -&gt; b<br>
&gt;<br>
&gt; There&#39;s an implicit forall for b, meaning that the caller of the<br>
&gt; method gets to choose what it wants for b (as long as it&#39;s an instance<br>
&gt; of Bar). For you to be able to write such a method you&#39;d need to write<br>
&gt; functions that can return any instance of Bar. One solution to this is<br>
&gt; to turn on the GHC extension -XTypeFamilies, and then modify your code<br>
&gt; as follows:<br>
&gt;<br>
&gt; class Cls c where<br>
&gt;    type Ret c :: * -- or a better name<br>
&gt;    foo :: c -&gt; Ret c<br>
&gt;<br>
&gt; instance Cls G where<br>
&gt;    type Ret G = FU<br>
&gt;    foo = fuu<br>
&gt;<br>
&gt; That should work (although I haven&#39;t tested it).<br>
&gt;<br>
&gt; What type families do in this case is allow you to write not only<br>
&gt; methods associated with typeclasses, but type functions associated<br>
&gt; with them too. In this case you can think of Ret as a function that<br>
&gt; takes a type (G in the instance above) and returns another type (FU).<br>
&gt; Each instance can define new mappings for Ret.<br>
&gt;<br>
&gt; Hope this helps!<br>
&gt;<br>
&gt; Dan<br>
&gt; On Tue, Sep 29, 2009 at 10:48 PM, DNM &lt;<a href="mailto:dnmehay@gmail.com">dnmehay@gmail.com</a>&gt; wrote:<br>
&gt;&gt; Correction by the author:<br>
&gt;&gt;<br>
&gt;&gt;&gt; It seems that ghc doesn&#39;t like the fact that I am saying &#39;foo&#39; must<br>
&gt;&gt;&gt; return a class &#39;b&#39; of typeclass &#39;Bar&#39;, while providing a function that<br>
&gt;&gt;&gt; returns a concrete data instance of &#39;Bar&#39; (viz., FU or FI) later on<br>
&gt;&gt;&gt; when I implement &#39;foo&#39; in each type classes.<br>
&gt;&gt;<br>
&gt;&gt; Should read:<br>
&gt;&gt;<br>
&gt;&gt; It seems that ghc doesn&#39;t like the fact that I am saying &#39;foo&#39; must<br>
&gt;&gt; return something of TYPE &#39;b&#39; implementing typeclass &#39;Bar&#39;, while<br>
&gt;&gt; providing<br>
&gt;&gt; a function that returns a concrete data instance of &#39;Bar&#39; (viz., FU or<br>
&gt;&gt; FI)<br>
&gt;&gt; later on when I implement &#39;foo&#39; in each type classes.<br>
&gt;&gt;<br>
&gt;&gt; On Sep 29, 10:43 pm, DNM &lt;<a href="mailto:dnme...@gmail.com">dnme...@gmail.com</a>&gt; wrote:<br>
&gt;&gt;&gt; N.B. I&#39;m a newbie to Haskell, and this problem is a bit complex, so<br>
&gt;&gt;&gt; bear with me.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; I&#39;m using typeclasses to implement a sort of common interface for all<br>
&gt;&gt;&gt; things -- call them things of type &#39;Cls&#39; -- that can be expected to<br>
&gt;&gt;&gt; implement a set of functions -- an &#39;interface&#39; in OOP-speak.  (Yes,<br>
&gt;&gt;&gt; yes, I&#39;m aware that typeclasses are subtly different and far superior,<br>
&gt;&gt;&gt; but my Haskell-ese is still a bit rudimentary.)<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Essentially, I want to have a typeclass that expects its instances to<br>
&gt;&gt;&gt; have an accessor function that results in something that is an<br>
&gt;&gt;&gt; instance of another typeclass whose instances can perform some<br>
&gt;&gt;&gt; operation.   The ghc type-checker doesn&#39;t seem to like my code,<br>
&gt;&gt;&gt; though, and I can&#39;t seem to figure out why.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; To make it concrete, I&#39;ve typed up some dummy typeclasses and a dummy<br>
&gt;&gt;&gt; function that uses their instances to illustrate what I mean, as well<br>
&gt;&gt;&gt; as the form of the ghc(i) error.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; ------------- BEGIN CODE ------------------<br>
&gt;&gt;&gt; class Cls c where<br>
&gt;&gt;&gt;     foo :: (Bar b) =&gt; c -&gt; b<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; class Bar b where<br>
&gt;&gt;&gt;     toNum :: b -&gt; Int<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; -- | One implementation of Cls<br>
&gt;&gt;&gt; data D = D {fu :: FU}<br>
&gt;&gt;&gt; data FU = FU {num :: Int}<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; instance Cls D where<br>
&gt;&gt;&gt;     foo = fu<br>
&gt;&gt;&gt; instance Bar FU  where<br>
&gt;&gt;&gt;     toNum f = (num f) + 47<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; -- | Another implementation of Cls<br>
&gt;&gt;&gt; data E = E {fi :: FI}<br>
&gt;&gt;&gt; data FI = FI {nuum :: Int}<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; instance Cls E where<br>
&gt;&gt;&gt;     foo = fi<br>
&gt;&gt;&gt; instance Bar FI where<br>
&gt;&gt;&gt;     toNum f = (nuum f) + 100<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; -- | Yet another (this one re-uses FI)<br>
&gt;&gt;&gt; data F = F {fii :: FI}<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; instance Cls F where<br>
&gt;&gt;&gt;     foo = fii<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; -- | And one last one, just to stress that<br>
&gt;&gt;&gt; --   I really need to implement multiple<br>
&gt;&gt;&gt; --  instances of Cls.<br>
&gt;&gt;&gt; data G = G {fuu :: FU}<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; instance Cls G where<br>
&gt;&gt;&gt;     foo = fuu<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; -- | Good. Now, the function &#39;useThisStuff&#39; need<br>
&gt;&gt;&gt; --   not know anything about it&#39;s payload<br>
&gt;&gt;&gt; --   other than that it its args are Cls&#39;s<br>
&gt;&gt;&gt; --   (hence they are foo&#39;able things that<br>
&gt;&gt;&gt; --   can be used to construct an Int answer).<br>
&gt;&gt;&gt; useThisStuff :: (Cls x, Cls y) =&gt; x -&gt; y -&gt; Int<br>
&gt;&gt;&gt; useThisStuff x y =<br>
&gt;&gt;&gt;     (toNum $ foo x) + (toNum $ foo y)<br>
&gt;&gt;&gt; ------------- END CODE --------------------<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; When I type this up in a file and try to load it in ghci, I get the<br>
&gt;&gt;&gt; following error message(s):<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; ------------- BEGIN ERROR MSG ----------<br>
&gt;&gt;&gt; Prelude&gt; :load Typeclasses.hs<br>
&gt;&gt;&gt; [1 of 1] Compiling Typeclasses      ( Typeclasses.hs, interpreted )<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Typeclasses.hs:14:10:<br>
&gt;&gt;&gt;     Couldn&#39;t match expected type `b&#39; against inferred type `FU&#39;<br>
&gt;&gt;&gt;       `b&#39; is a rigid type variable bound by<br>
&gt;&gt;&gt;           the type signature for `foo&#39; at Typeclasses.hs:4:16<br>
&gt;&gt;&gt;       Expected type: D -&gt; b<br>
&gt;&gt;&gt;       Inferred type: D -&gt; FU<br>
&gt;&gt;&gt;     In the expression: fu<br>
&gt;&gt;&gt;     In the definition of `foo&#39;: foo = fu<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Typeclasses.hs:23:10:<br>
&gt;&gt;&gt;     Couldn&#39;t match expected type `b&#39; against inferred type `FI&#39;<br>
&gt;&gt;&gt;       `b&#39; is a rigid type variable bound by<br>
&gt;&gt;&gt;           the type signature for `foo&#39; at Typeclasses.hs:4:16<br>
&gt;&gt;&gt;       Expected type: E -&gt; b<br>
&gt;&gt;&gt;       Inferred type: E -&gt; FI<br>
&gt;&gt;&gt;     In the expression: fi<br>
&gt;&gt;&gt;     In the definition of `foo&#39;: foo = fi<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Typeclasses.hs:31:10:<br>
&gt;&gt;&gt;     Couldn&#39;t match expected type `b&#39; against inferred type `FI&#39;<br>
&gt;&gt;&gt;       `b&#39; is a rigid type variable bound by<br>
&gt;&gt;&gt;           the type signature for `foo&#39; at Typeclasses.hs:4:16<br>
&gt;&gt;&gt;       Expected type: F -&gt; b<br>
&gt;&gt;&gt;       Inferred type: F -&gt; FI<br>
&gt;&gt;&gt;     In the expression: fii<br>
&gt;&gt;&gt;     In the definition of `foo&#39;: foo = fii<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Typeclasses.hs:39:10:<br>
&gt;&gt;&gt;     Couldn&#39;t match expected type `b&#39; against inferred type `FU&#39;<br>
&gt;&gt;&gt;       `b&#39; is a rigid type variable bound by<br>
&gt;&gt;&gt;           the type signature for `foo&#39; at Typeclasses.hs:4:16<br>
&gt;&gt;&gt;       Expected type: G -&gt; b<br>
&gt;&gt;&gt;       Inferred type: G -&gt; FU<br>
&gt;&gt;&gt;     In the expression: fuu<br>
&gt;&gt;&gt;     In the definition of `foo&#39;: foo = fuu<br>
&gt;&gt;&gt; Failed, modules loaded: none.<br>
&gt;&gt;&gt; ------------- END ERROR MSG ------------<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; It seems that ghc doesn&#39;t like the fact that I am saying &#39;foo&#39; must<br>
&gt;&gt;&gt; return a class &#39;b&#39; of typeclass &#39;Bar&#39;, while providing a function that<br>
&gt;&gt;&gt; returns a concrete data instance of &#39;Bar&#39; (viz., FU or FI) later on<br>
&gt;&gt;&gt; when I implement &#39;foo&#39; in each type classes.  Repeated for<br>
&gt;&gt;&gt; convenience:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; class Cls c where<br>
&gt;&gt;&gt;     foo :: (Bar b) =&gt; c -&gt; b<br>
&gt;&gt;&gt; ...<br>
&gt;&gt;&gt; -- (e.g.)<br>
&gt;&gt;&gt; data G = G {fuu :: FU}<br>
&gt;&gt;&gt; instance Cls G where<br>
&gt;&gt;&gt;     foo = fuu<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Does anyone have any clue as to what I&#39;m doing wrong (language<br>
&gt;&gt;&gt; extensions that I may need, etc.)?<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Is is because I&#39;m using context restrictions on the *result* type of a<br>
&gt;&gt;&gt; typeclass method?  I&#39;ve written other typeclasses with methods that<br>
&gt;&gt;&gt; say, essentially:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; class A a where<br>
&gt;&gt;&gt;     blah :: (MonadPlus m) =&gt; a -&gt; a -&gt; m a<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; with no issues. The restriction there is not on the return type a, but<br>
&gt;&gt;&gt; rather on some monadic &#39;wrapper&#39; around it.  This may be why that code<br>
&gt;&gt;&gt; works.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Please advise.  Any help is greatly appreciated.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; --D.N. (Dennis)<br>
&gt;&gt;&gt; _______________________________________________<br>
&gt;&gt;&gt; Haskell-Cafe mailing list<br>
&gt;&gt;&gt; Haskell-C...@haskell.orghttp://<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; Haskell-Cafe mailing list<br>
&gt;&gt; <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
&gt;&gt; <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
&gt;&gt;<br>
&gt; _______________________________________________<br>
&gt; Haskell-Cafe mailing list<br>
&gt; <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
&gt; <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
&gt;<br>
&gt;<br>
<br>
</div></div><font color="#888888">--<br>
View this message in context: <a href="http://www.nabble.com/Problem-with-result-type-context-restrictions-in-typeclasses.-tp25674141p25675199.html" target="_blank">http://www.nabble.com/Problem-with-result-type-context-restrictions-in-typeclasses.-tp25674141p25675199.html</a><br>

Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.<br>
</font><div><div></div><div class="h5"><br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br>