<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">On 08/25/2016 10:57 PM, Daniel
      Abrahamsson wrote:<br>
    </div>
    <blockquote
cite="mid:CAJL2zxX+S1S48=RW8CPmyybSHym+kA5EputyVa4va1jZxSbRRg@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div class="gmail_default"
          style="font-family:arial,helvetica,sans-serif">You can achieve
          something close to what you are after by using opaque types.
          Partly re-using your original example:</div>
        <div class="gmail_default"
          style="font-family:arial,helvetica,sans-serif"><br>
        </div>
        <div class="gmail_default" style="">
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">-module(string_with_case).</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif"><br>
            </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">-opaque lowercase() :: string().</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">-opaque uppercase() :: string().</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">-type anycase() :: lowercase() |
              uppercase() | string().</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif"><br>
            </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">-export_type([ lowercase/0</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">             , uppercase/0</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">             ]).</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif"><br>
            </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">-export([ uppercase/1</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">        , lowercase/1</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">        , need_lower/1</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">        , concat/2</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">        ]).</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif"><br>
            </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">-spec lowercase(anycase()) ->
              lowercase().</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">lowercase(Str) ->
              string:to_lower(Str).</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif"><br>
            </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">-spec uppercase(anycase()) ->
              uppercase().</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">uppercase(Str) ->
              string:to_upper(Str).</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif"><br>
            </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">-spec need_lower(lowercase()) ->
              ok. </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">need_lower(_Lower) -> ok. </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif"><br>
            </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">-spec concat(anycase(), anycase())
              -> string().</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">concat(A, B) -> A ++ B.</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif"><br>
            </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif"><br>
            </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">Note that these two (maybe in your
              eyes valid) examples will NOT pass dialyzer:</font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif"><br>
            </font></div>
          <div class="gmail_default" style=""><font face="arial,
              helvetica, sans-serif">string_with_case:need_lower("example").
              % FAILS: Breaks opaqueness of
              string_with_case:lowercase().</font></div>
          <div style="font-family:arial,helvetica,sans-serif"><br>
          </div>
          <div style="font-family:arial,helvetica,sans-serif">string_with_case:lowercase("test")
            ++ "mixing". % FAILS: Breaks opaqueness of
            string_with_case:lowercase().</div>
          <div><br>
          </div>
          <div>In other words, all operations involving types
            uppercase() or lowercase() must take place inside the
            string_with_case module.</div>
          <div>If you need to operate on a lowercase() as if it were a
            string outside the string_with_case module, you must provide
            a to_string function:</div>
          <div><br>
          </div>
          <div>-spec to_string(anycase()) -> string().</div>
          <div>to_string(X) -> X.</div>
          <div><br>
          </div>
          <div>This of course means you would have to call the
            lowercase/1 or uppercase/1 functions again to convert it
            back, should you need to</div>
          <div>use the "variant/sort specific" functions of
            string_with_case on the result. This is however necessary to
            maintain the guarantees you are trying to achieve.</div>
          <div><br>
          </div>
          <div>//Daniel</div>
        </div>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
erlang-questions mailing list
<a class="moz-txt-link-abbreviated" href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a>
<a class="moz-txt-link-freetext" href="http://erlang.org/mailman/listinfo/erlang-questions">http://erlang.org/mailman/listinfo/erlang-questions</a>
</pre>
    </blockquote>
    <tt>This approach works in a closed-system that only relies on the
      opaque types.  If the opaque types are not always used as opaque
      types, i.e., in a way that depends on it being a list of integers,
      then that will just generate dialyzer errors.  Also, the fact
      remains that it does not actually check the contents of the list,
      so this approach depends on the developer always using the opaque
      types in the proper way (i.e., it isn't as if development errors
      with the opaque types will be easily caught based on the contents
      of the list of integers).  Since software is normally not
      developed in complete isolation, requiring complete isolation for
      a solution is not helpful for any system that might want to grow
      in the future.</tt><br>
  </body>
</html>