[m-users.] Instantiatedness and handling io results

Julian Fondren jfondren at minimaltype.com
Sun Aug 4 19:37:10 AEST 2019


On 2019-08-04 03:38, Julian Fondren wrote:
> On 2019-08-04 02:48, Philip White wrote:
>> 2. What is the idiomatic way of handling a sequence of things which
>> return results? In Haskell, there is do-notation for sequencing 
>> monads,
>> but I haven't seen any monads in mercury.
> 
> I don't expect you to agree, but the xkcd joke about regular
> expressions is how I think about Haskell solutions to problems.

Try the following out.

And then, change 'semidet_from_char_list' to 'from_char_list' in main/2,
and try and understand the resulting error message.

   :- module readtwo4.
   :- interface.
   :- import_module io.
   :- pred main(io::di, io::uo) is det.
   :- implementation.
   :- import_module string, list, maybe, char.

   main(!IO) :-
       Read = read_word
           >> semidet_from_char_list
           >> to_int
           // die("bad read"),
       Read(N, !IO),
       Read(M, !IO),
       foldl(io.write_line, (N .. M), !IO).

   :- pred die(string::in) is erroneous.
   :- pragma foreign_proc("C",
       die(Reason::in),
       [promise_pure, will_not_call_mercury],
   "
       puts(Reason);
       exit(1);
   ").

   %------------------------------------------------------------%
   %  /     \
   % | () () |
   %  \  ^  /
   %   |||||
   %   |||||
   %------------------------------------------------------------%
   :- type producer(T) == (pred(T, io, io)).
   :- inst producer == (pred(out, di, uo) is det).

   :- type resulter(T) == producer(io.result(T)).
   :- inst resulter == producer.

   :- type transformer(A, B) == (pred(A, B)).
   :- inst transformer == (pred(in, out) is semidet).

   :- type effect == (pred).
   :- inst effect == ((pred) is erroneous).

   :- func resulter(A) >> transformer(A, B) = resulter(B).
   :- mode in(resulter) >> in(transformer) = out(resulter).
   R1 >> T = R2 :-
       R2 = (pred(Res::out, !.IO::di, !:IO::uo) is det :-
           R1(Res0, !IO),
           (
               Res0 = ok(X1),
               ( if T(X1, X2) then
                   Res = ok(X2)
               else
                   Res = error(make_io_error("transformation failed"))
               )
           ;
               Res0 = eof,
               Res = eof
           ;
               Res0 = error(E),
               Res = error(E)
           )).

   :- func resulter(T) // effect = producer(T).
   :- mode in(resulter) // in(effect) = out(producer).
   R // E = P :-
       P = (pred(Res::out, !.IO::di, !:IO::uo) is det :-
           R(Res0, !IO),
           ( if Res0 = ok(Res1) then
               Res = Res1
           else
               E
           )).


More information about the users mailing list