Skip to content

The Great Renaming, Chapter 9: Monadic and applicative operators#379

Merged
jmid merged 3 commits intoc-cube:mainfrom
jmid:monadic-applicative-renaming
Dec 4, 2025
Merged

The Great Renaming, Chapter 9: Monadic and applicative operators#379
jmid merged 3 commits intoc-cube:mainfrom
jmid:monadic-applicative-renaming

Conversation

@jmid
Copy link
Collaborator

@jmid jmid commented Dec 3, 2025

Having slayed the int dragon, we are left with a only a few less interesting challengesm including the monadic and applicative operators. The current status here is as follows:

Combinator name QCheck.Gen QCheck.arbitrary QCheck2.Gen
always - ?print:'a Print.t -> 'a -> 'a arbitrary -
return 'a -> 'a t - 'a -> 'a t
pure 'a -> 'a t - 'a -> 'a t
bind - - 'a t -> ('a -> 'b t) -> 'b t
(>>=) 'a t -> ('a -> 'b t) -> 'b t - 'a t -> ('a -> 'b t) -> 'b t
ap - - ('a -> 'b) t -> 'a t -> 'b t
(<*>) ('a -> 'b) t -> 'a t -> 'b t - ('a -> 'b) t -> 'a t -> 'b t
(> =) 'a t -> ('a -> 'b) -> 'b t -
(<$>) ('a -> 'b) -> 'a t -> 'b t - ('a -> 'b) -> 'a t -> 'b t
join 'a t t -> 'a t - 'a t t -> 'a t

Observations:

  • QCheck.Gen and QCheck2.Gen offer a monadic and applicative interface with similar operators whereas QCheck.arbitrary doesn't
  • bind is missing from QCheck.Gen
  • ap missing from QCheck.Gen
  • QCheck.always sticks out - it is an equivalent to return/pure. A quick search shows that it is used in Tezos and Goblint.

i initially went for adding always as a third alias to both QCheck.Gen and QCheck2.Gen for consistency, but then regretted and rolled back. My thinking is:

  • since QCheck.arbitrary doesn't and cannot offer a monadic or applicative interface it doesn't make sense to provide return or pure for it, as it might confuse more than it helps.
  • addng a third name always to both QCheck.Gen and QCheck2.Gen for existing functionality doesn't bring any direct value, more likely it will just make it harder to read 3 names for the same thing.

Alas, I've gone only with adding the missing bind and ap names to QCheck.Gen resulting in the following:

Combinator name QCheck.Gen QCheck.arbitrary QCheck2.Gen
always - ?print:'a Print.t -> 'a -> 'a arbitrary -
return 'a -> 'a t - 'a -> 'a t
pure 'a -> 'a t - 'a -> 'a t
bind 'a t -> ('a -> 'b t) -> 'b t - 'a t -> ('a -> 'b t) -> 'b t
(>>=) 'a t -> ('a -> 'b t) -> 'b t - 'a t -> ('a -> 'b t) -> 'b t
ap ('a -> 'b) t -> 'a t -> 'b t - ('a -> 'b) t -> 'a t -> 'b t
(<*>) ('a -> 'b) t -> 'a t -> 'b t - ('a -> 'b) t -> 'a t -> 'b t
(> =) 'a t -> ('a -> 'b) -> 'b t -
(<$>) ('a -> 'b) -> 'a t -> 'b t - ('a -> 'b) -> 'a t -> 'b t
join 'a t t -> 'a t - 'a t t -> 'a t

This result is consistent across QCheck.Gen and QCheck2.Gen 🤷

@jmid jmid merged commit 2cb9592 into c-cube:main Dec 4, 2025
46 of 47 checks passed
@jmid jmid deleted the monadic-applicative-renaming branch December 4, 2025 15:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant