How to use Core.Command monadic operator cleanly (with many arguments function

I’m writing a CLI with Core.command and to write the command I need to apply a function f : 'a1 -> 'a2 -> ... -> 'an -> unit -> unit to arguments 'a1 t, 'a2 t, ... 'an t after trying some stuff, I ended up finding monadic binary operators :

(*>) : unit t -> 'a t -> 'a t 
(<*) : 'a t -> unit t -> 'a t 
(<*>) : ('a -> 'b) t -> 'a t -> 'b t 
(>>|) : 'a t -> ('a -> 'b) -> 'b t

So I end up writing f +> a1 <*> a2 <*> ... <*> an with +> being >>| but flipped, which works fine but left me with some question.I don’t understand the point of *> and <* . For me they don’t make any sense.
I don’t understand how to use >>| correctly with many argument functions. (In my case that would be a1 >>| f <*> a2 ... <*> an which is just weird.
Or is there a way to use >>| better ? I thought that a1 <*> .... <*> an >>| f could be nice but that doesn’t really work either, you would need <*> to be flipped and change the priority of operation.
Do you guys have some ideas?

You probably want to use return : 'a -> 'a t on f before applying it to a1,…,an with <*>: return f <*> a1 <*> ... <*> an.

With Command I find it’s really helpful to use the let-syntax, if you’re able to use ppx.

Your example would become something like:

let param =
  let%map_open.Command a1 = a1
  and a2 = a2
  and a3 = a3 in
  fun () -> f a1 a2 a3
;;
1 Like

And if not, it looks pretty easy to use let-ops which can be defined easily in the language itself:

let ( let+ ) = Command.Let_syntax.( >>| )
let ( and+ ) = Command.Let_syntax.Let_syntax.both

let param =
  let+ a1 = a1 (* This will pretty soon be just 'let+ a1' *)
  and+ a2 = a2
  and+ a3 = a3 in
  fun () -> f a1 a2 a3
1 Like

Command is definitely designed to be used with let-syntax (specifically with the %map_open ppx but using (let+) should also work), see the relevant chapter of Real World OCaml for a useful guide.

Thank for your answer. Du to the lager number of command and command parameters (20 * 10).
I decieded to keep my current solution for the moment.

When we have let-punning. I’ll change to let+ a1 and+ a2 ... and+ an in f a1 a2 a3

1 Like

Let-punning is available since OCaml 4.13.1 .

1 Like

One of our dependency force un to stay at version 4.12.1 for some reason

Let me guess, Batteries? It has a weird restriction and needs to be manually updated for each OCaml version. I think because of the way it uses Stdlib modules.

EDIT: it looks like they’ve landed but not yet release 4.13 support: OCaml 4.13 support · Issue #1045 · ocaml-batteries-team/batteries-included · GitHub

Batteries with 4.13 support was just released yesterday: Release batteries.3.4.0 by kit-ty-kate · Pull Request #20225 · ocaml/opam-repository · GitHub

2 Likes

Thanks, but it’s not batteries, it’s Tezos ^^ (would be weird to mix Core and Batteries) ?