You can't really flip the arguments in a way that A : Set
comes after x : A
.
You already mentioned syntax
, which I think is the best solution. This works because Agda will transform x <[ A ] y
into cmp A x y
and that's fine with the type checker.
Here's another (rather ugly and hacky) approach. Let's say we have:
_<[_]_ : {A : Set} → A → ? → A → Set
Here we can exploit unification a bit: by using something that mentions A
in the ?
hole, we can force the type checker to fill in the implicit A
in front. But as far as I know, there's no simple type we can use in place of ?
, so that we get the required x <[ A ] y
. But to finish the thought, here's one thing that works:
data Is : Set → Set₁ where
is : (A : Set) → Is A
_<[_]_ : {A : Set} → A → Is A → A → Set
x <[ is A ] y = cmp A x y
Yes, this is fairly ugly and I would recommend against it.
But back to your question about syntax
: I would not consider syntax
to be a hack in any way. In fact, the standard library uses syntax
in roughly the same way in one place (Data.Plus
to be exact):
syntax Plus R x y = x [ R ]⁺ y
Even having cmp-explicit
around is useful. I would even go as far as to suggest you make two extra versions:
cmp-syntax = cmp
cmp-explicit-syntax = λ A b → cmp A {{b}}
syntax cmp-syntax A x y = x <[ A ] y
syntax cmp-explicit-syntax A b x y = x <[ A at b ] y
If the user of your module does not want to use the syntactic shortcut (for example, he imports another module that defines _<[_]_
), he can simply choose to not import it and still have cmp
around.
Again, standard library does this with the syntactic shortcut for Σ
. The shortcut allows you to write:
open import Data.Nat
open import Data.Product
open import Relation.Binary.PropositionalEquality
x : Σ[ n ∈ ℕ ] n + 2 ≡ 4
x = 2 , refl
And if you do not want it, then you simply:
open import Data.Product
hiding (Σ-syntax)