[m-users.] A neater way to call chained init functions?

Julian Fondren jfondren at minimaltype.com
Fri Jul 26 04:48:49 AEST 2019


On 2019-07-25 11:43, emacstheviking wrote:
> Given these three library init predicates...
> 
> :- pred setup_sdl(bool::out, io::di, io::uo) is det.
> :- pred setup_sdlmix(bool::out, io::di, io::uo) is det.
> :- pred setup_sdlimg(bool::out, io::di, io::uo) is det.
> 
> is there a more idiomatic / efficient / less $%^&*( ugly way to do
> this please...
> 
> :- pred setup_app(bool::out, io::di, io::uo) is det.
> 
> setup_app(CanRun, !IO) :-
>     setup_sdl(SdlUp, !IO),
>     (
>         SdlUp = yes,
>         setup_sdlimg(ImgUp, !IO),
>         (
>             ImgUp = yes,
>             setup_sdlmix(MixUp, !IO),
>             (
>                 MixUp = yes,
>                 CanRun = yes
>             ;
>                 MixUp = no,
>                 CanRun = no
>             )
>         ;
>             ImgUp = no,
>             CanRun = no
>         )
>     ;
>         SdlUp = no,
>         CanRun = no
>     ).
> 
>  IIUIC you can't have predicates being anything other than `det` if
> they use IO ?

They can be cc_multi, but you still can't use them in a
conditional. I suppose that you could use exceptions instead, to
get the same pattern of

   a bunch,
   of stuff,
   that could fail,
   at any time,
   and we'll handle that
...
   success case
...
   failure case

Anyway, as these all have the same type, you could process a list
of them. And even when they don't have the same type, you could
provide earlier parameters to curry them into this same type.

Like so:

   :- module initall.
   :- interface.
   :- import_module io.
   :- pred main(io::di, io::uo) is det.
   :- implementation.
   :- import_module list, bool.

   :- type initializer == (pred(bool, io, io)).
   :- inst initializer for list/1
       --->    []
       ;       [pred(out, di, uo) is det | initializer].

   :- pred init_all(list(initializer), bool, io, io).
   :- mode init_all(in(initializer), out, di, uo) is det.
   init_all([], yes, !IO).
   init_all([P | Ps], OK, !IO) :-
       P(Res, !IO),
       (
           Res = yes,
           init_all(Ps, OK, !IO)
       ;
           Res = no,
           OK = no
       ).

   :- pred setup_sdl(bool::out, io::di, io::uo) is det.
   :- pred setup_sdlmix(bool::out, io::di, io::uo) is det.
   :- pred setup_sdlimg(bool::out, io::di, io::uo) is det.
   :- pred setup_sdlmaybe(bool::in, bool::out, io::di, io::uo) is det.

   setup_sdl(yes, !IO) :- io.write_string("at sdl\n", !IO).
   setup_sdlmix(yes, !IO) :- io.write_string("at sdlmix\n", !IO).
   setup_sdlimg(yes, !IO) :- io.write_string("at sdlimg\n", !IO).
   setup_sdlmaybe(B, B, !IO) :-
       io.write_string("at sdlmaybe: ", !IO),
       io.write_line(B, !IO).

   main(!IO) :-
       init_all([setup_sdl, setup_sdlmaybe(yes), setup_sdlmix, 
setup_sdlimg],
           Res, !IO),
       io.write_line(Res, !IO).

Run it, change the 'yes' param to 'no', try again.

It might also work, if SDL permits you to try to initialize stuff
that shouldn't be initialized, to collect outputs and test them
afterwards.

   setup_sdl(Res1, !IO),
   setup_sdlmix(Res2, !IO),
   setup_sdlimg(Res3, !IO),
   ( if all [X] (list.member(X, [Res1, Res2, Res3) => X = yes) then
       io.write_string("sdl initialized\n", !IO)
   else
       io.write_string("somethign failed\n", !IO)
   ).

That's the nondet list.member/2 btw.

> The above code is classic staircase, in Haskell I'd hear
> "maybe monads" screaming at me but I have not yet gotten exposure to
> the std_util maybe wrapper...it seems to be just a normal type
> constructor with yes(T) and no, and also maybe_error as well. All
> suggestions welcome!!
> 
>  It's going well, I have sounds, images, lines, rectangles all in a
> window but I am now trying to get away from the FFI and start to learn
> more idiomatic Mercury.

Cool.

> 
>  Thanks,
>  Sean
> _______________________________________________
> users mailing list
> users at lists.mercurylang.org
> https://lists.mercurylang.org/listinfo/users


More information about the users mailing list