<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <font face="Courier"><br>
    </font>
    <div class="moz-forward-container"><font face="Courier">In other
        words, building mod2 as a library should not be possible </font>
      <blockquote type="cite"
        cite="mid:20210514181244.GX1331@kola.localdomain">
        <blockquote type="cite">
          <pre class="moz-quote-pre" wrap=""><font face="Courier">without an error or at least a warning.
</font></pre>
        </blockquote>
        <pre class="moz-quote-pre" wrap=""><font face="Courier">Ok, so it would be a warning like --warn-dead-preds but the analysis
would be much more difficult. </font></pre>
      </blockquote>
      <p><font face="Courier">You phrased the intuition underlying my
          'pragmatic user' remark. A library typeclass predicate should
          not be allowed to compiled into a library if there is no type
          to satisfy the typeclass constraint.<br>
        </font> </p>
      <blockquote type="cite"
        cite="mid:20210514181244.GX1331@kola.localdomain">
        <pre class="moz-quote-pre" wrap=""><font face="Courier">I don't know how difficult, but just
for thought:

    :- module m1.
    :- interface.

    :- typeclass tc(T) where [
        pred eval(T::in, int::out) is det
    ].

    :- type foo
        --->    some [T] foo(T) => tc(T).

    :- func make_foo = foo.

    :- pred eval_foo(foo::in, int::out) is det.

    %-------------------------------------------%

    :- implementation.

    :- instance tc(int) where [
        eval(I, I)
    ].

    make_foo = 'new foo'(42).

    eval_foo(Foo, I) :-
        Foo = foo(X),
        eval(X, I).

It's plausible that because:
(1) make_foo is exported
(2) make_foo returns a foo
(3) foo has a class constraint tc(T)
(4) the make_foo implementation returns a foo where
    the existentially quantified type variable T = int

then we could deduce that 'instance tc(int)' is usable,
but it's highly unlikely anyone will implement such a thing.

Peter
</font></pre>
      </blockquote>
      <p><font face="Courier">Stimulated piece of coding. <br>
        </font> </p>
      <p><font face="Courier">If I understand you well, there might be
          convoluted cases in which an exported typeclass, without an
          abstract instance in the interface, could probably be used in
          a parent file if the type instantiation is somehow
          bootstrapped (or 'lifted up') by existential quantification
          plus symbol export in the interface of the module. But
          (reassuringly?) this does not work. Yes, your module m1 does
          build into a library, but the ominous "unsatisfiable typeclass
          contraint" error message pops up again if you try to import
          module m1 into a parent file and use 'eval' like this:</font></p>
      <blockquote>
        <p><font face="Courier">:- module test4.<br>
            :- interface.<br>
            :- import_module io.<br>
            :- pred main(io::di, io::uo) is det. <br>
          </font> </p>
        <p><font face="Courier">:- implementation.<br>
             <br>
            :- import_module int, string, list.<br>
            :- import_module m1.<br>
          </font> <font face="Courier"><br>
            main(!IO) :- <br>
                eval(42, I),<br>
                io.format("this int: %d\n", [i(I)], !IO). <br>
          </font> </p>
      </blockquote>
      <p><font face="Courier">Building your m1 module (as-is) and test4,
          using DEV compiler (at HEAD), with: <br>
        </font> </p>
      <blockquote>
        <p><font face="Courier">/usr/local/mercury-DEV/bin/mmc  -E 
            --make libm1</font></p>
        <p><font face="Courier">/usr/local/mercury-DEV/bin/mmc -E  
            --make test4 </font></p>
      </blockquote>
      <p><font face="Courier">I obtain:</font></p>
      <blockquote>
        <p><font face="Courier">test4.m:014: In clause for predicate
`main'/2:                                                                                                                      
            <br>
            test4.m:014:   unsatisfiable typeclass
constraint:                                                                                                                  
            <br>
            test4.m:014:  
`m1.tc(int)'.                                                                                                                                       
            <br>
            ** Error making `Mercury/cs/test4.c'. <br>
          </font> </p>
      </blockquote>
      <p><font face="Courier">So after all, implementing something like
          a '--no-unsatisfiable-typeclass' warning option in the
          compiler may well be easier than expected.<br>
        </font> </p>
      <p><font face="Courier">Coming back to my first post code, I now
          realize I have to slightly correct my remark. <br>
        </font> </p>
      <p><font face="Courier">An error message cannot and should not be
          issued at library compile time as it is correct Mercury syntax
          (and good common sense) to satisfy the typeclass instantiation
          constraint anywhere else than in module mod2. So it is not
          strictly necessary for an abstract instance declaration to be
          present in the **same** module as the typeclass declaration. <br>
        </font> </p>
      <p><font face="Courier">E.g., the following builds and runs fine:</font></p>
      <blockquote>
        <p><font face="Courier">%------- file mod3.m
            -----------------------------%<br>
          </font> </p>
        <p><font face="Courier">:- module
            mod3.                              <br>
            :- interface.                               <br>
            :- import_module string.                    <br>
          </font> <font face="Courier"><br>
            :- typeclass eval_type(T) where [<br>
                pred eval(T),<br>
                mode eval(out) is det<br>
            ].</font></p>
        <p><font face="Courier">%------- file mod4.m
            -----------------------------%<br>
          </font> </p>
        <p><font face="Courier">:- module mod4.<br>
            :- interface.<br>
            :- import_module mod3.<br>
          </font> <font face="Courier"><br>
            :- instance eval_type(string).              <br>
          </font> <font face="Courier"><br>
            :- implementation.                          <br>
          </font> <font face="Courier"><br>
            :- instance eval_type(string) where [<br>
                   pred(eval/1) is eval_string<br>
               ].<br>
          </font> <font face="Courier"><br>
            :- pred eval_string(string::out) is det.<br>
          </font> <font face="Courier"><br>
            eval_string(Result) :- Result = "a". <br>
          </font> </p>
        <p><font face="Courier">%------ file test4.m
            ----------------------------%<br>
          </font> </p>
        <p><font face="Courier">:- module
            test4.                            <br>
            :- interface.                               <br>
            :- import_module io.<br>
            :- pred main(io::di, io::uo) is det.<br>
          </font> <font face="Courier"><br>
            :- implementation.<br>
          </font> <font face="Courier"><br>
            :- import_module string, list.<br>
            :- import_module mod3, mod4.<br>
          </font> <font face="Courier"><br>
            main(!IO) :- <br>
                eval(S), <br>
                io.format("this string: %s\n", [s(S)], !IO).<br>
            %------------------------------------------------%</font></p>
      </blockquote>
      <p><font face="Courier">So, the 'pragmatic' improvement that I am
          advocating could not go beyond a warning message at library
          compile time.</font></p>
      <p><font face="Courier">Alternatively, it could be implemented in
          the linker after all the dependency graph has been resolved,
          if it is found that there is a typeclass with no one type to
          satisfy it.<br>
        </font> </p>
      <p><font face="Courier">Fabrice.<br>
        </font> </p>
    </div>
  </body>
</html>