<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>I've recently bumped into the following constraint, which does
      not seem to me to be quite clearly documented (either in the
      reference manual or the user manual) and perhaps should be. (But
      then it may be that I did not search hard enough).<br>
    </p>
    <p>When a module typeclass is imported into a parent Mercury source
      file using ':- import_module', it so appears that the module
      interface should contain an abstract instance declaration
      corresponding to each usable type of the exported typeclass.
      Otherwise, the compiler will issue an error message to the effect
      that the typeclass constraint is unsatisfiable.<br>
    </p>
    <p>What may be puzzling to beginners and maybe more advanced testers
      is that this constraint does not show up if the typeclass in
      question is inlined in the parent source file.</p>
    <p>Below is a somewhat minimal example of this contrast:<br>
    </p>
    <blockquote>
      <p>%---- Inlined case: no abstract instance declaration ---- %</p>
      <p>:- module test3.                                               
        <br>
        :-
        interface.                                                      
        <br>
        :- import_module io.                                         <br>
        :- import_module string.                                   <br>
        :- pred main(io::di, io::uo) is det.<br>
                                                                        
        <br>
        :- typeclass eval_type(T) where [                     <br>
            pred
        eval(T),                                                 <br>
            mode eval(out) is det                                    <br>
].                                                                       
        <br>
        :- pred eval_string(string::out) is det.                <br>
                                                                         
        <br>
        :- implementation.                                             <br>
                                                                         
        <br>
        :- import_module list.                                         <br>
        :- instance eval_type(string) where [                 <br>
            pred(eval/1) is eval_string                                
        <br>
].                                                                       
        <br>
        eval_string(Result) :- Result = "a".                    <br>
                                                                         
        <br>
        main(!IO)
        :-                                                        <br>
           
        eval(S11),                                                     
        <br>
            io.format("this string: %s\n", [s(S11)], !IO). <br>
      </p>
      <p>%------------------------------------------------------------------------%<br>
      </p>
    </blockquote>
    <p>This file compiles and outputs: 'this string: a', and no abstract
      instance declaration is necessary (as expected).<br>
    </p>
    <p>In contrast, the following module mod2 will build into a library,
      **without any error message**, although it cannot be imported to
      any avail into a Mercury source file, as in this case the compiler
      will issue an error message ('typeclass constraint is
      unsatisfiable") on building the target executable test2:</p>
    <blockquote>
      <p>%------------------------------------------------------------------------%</p>
      <p>:- module mod2.<br>
        :- interface.<br>
        :- import_module string.<br>
                                                                                                                                          
        <br>
        :- typeclass eval_type(T) where [<br>
            pred eval(T), <br>
            mode eval(out) is det <br>
].                                                                                                                                        
        <br>
                                                                                                                                          
        <br>
        % :- instance eval_type(string).<br>
        <br>
        :- pred eval_string(string::out) is det. <br>
                                                                                                                                          
        <br>
        :- implementation.<br>
        <br>
        :- instance eval_type(string) where [<br>
            pred(eval/1) is eval_string <br>
        ].  <br>
        <br>
        eval_string(Result) :- Result = "a".<br>
      </p>
      <p>%------------------------------------------------------------------------%</p>
      <p>:- module test2.<br>
        :- interface.<br>
        :- import_module io. <br>
        :- pred main(io::di, io::uo) is det.</p>
      <p>:- implementation.</p>
      <p>:- import_module string, list.<br>
        :- import_module mod2.</p>
      <p>main(!IO) :-  <br>
            eval(S11),<br>
            io.format("this string: %s\n", [s(S11)], !IO),<br>
            io.nl(!IO). <br>
      </p>
    </blockquote>
    <p>      
%------------------------------------------------------------------------%                                                                                                                                   
      <br>
                                                                                                                                          
      <br>
      The error message on building test2 disappears if library mod2 is
      rebuilt **after uncommenting** the abstract instance declaration
      in the interface.</p>
    <p>Why there should be an abstract instance declaration in the
      interface of the module may be understood. <br>
    </p>
    <p>What is odd is that mod2 builds into a library whether the
      abstract instance declaration is present or not in the interface.
      <br>
    </p>
    <p>As a user, I would advise, if this makes any sense, to issue an
      error message at library compile time (since the typeclass will
      not be usable in parent source files). Or, minimally, document
      this requirement.<br>
    </p>
    <p><br>
    </p>
  </body>
</html>