I've just discovered what the `@<template_name>` notation in functions like `fetchByKey` et al means
So far I thought it was part of the key parameter, so that we know what template the key is part of (I’m not a Haskell pro - yet…).
It turns out that the @<template_name> notation belongs to the function, and it’s called visible type application in Haskell.
Here is a description: Visible Type Application in GHC 8 (Kwang’s Haskell Blog).
Kwang illustrates its use by the following example, compare:
λ> id "a"
"a"
λ> id (3 :: Int)
3
With using visible type annotation it becomes simpler:
λ> :set -XTypeApplications
λ> id @String "a"
"a"
λ> id @Int 3
3
For fetchByKey, thinking that the @<template_name> part belongs to the key argument, doesn’t cause a syntax error, because we don’t have parameters other than the key.
But for queryContractKey, which also has a party parameter, we have to keep in mind that the @<template_name> part must be written right after the function name, and this is the right syntax:
maybeDealer <- queryContractKey @Username [originator,operator] (operator, "DealerUser")
Another subtle thing which took me a while to understand is that the type applications need to appear in the order corresponding to the type parameters in the function. And this is tied in with the forall statement you may have sometimes seen.
For example, a full function signature is written like:
fmap : forall f a b . (a -> b) -> f a -> f b
writing fmap @Set would mean that f = Set, because it appears first in the forall statement. However, often you’ll see signatures with the forall omitted, e.g.:
fmap : (a -> b) -> f a -> f b
in which case the compiler will infer the order of variables from the signature. In this case, I think it would mean that writing fmap @Set would fail (someone correct me), because it would try to match Set : * -> * with a : *, the first type parameter, rather than f : * -> *, which appears third in that signature.
And that’s how I discovered what forall is for 
Here’s an actual example of what I’m talking about above:
Hi Luciano, that’s a very interesting problem. The solution mostly involves sprinkling a few more types across your code. Despite that, you will still need to enable the AllowAmbiguousTypes language extension because the type parameter f only appears within the type class constraints. First of all, you need to tell the compiler that you want to access the x field in updateInner's setField and getField: updateInner : forall x f. (Functor f, HasField x Outer (f Inner)) => (Inner -> Inner) -> Ou…
Thanks, that’s interesting, I saw forall many times but so far I didn’t dig deeper to understand what it’s for.
Let me introduce a little wrinkle. I added this to the trigger Daml library a while ago:
query : forall a m. (Template a, ActionTriggerAny m) => m [(ContractId a, a)]
query = implQuery
class ActionTriggerAny m where
implQuery : forall a. Template a => m [(ContractId a, a)]
We are indeed supporting the @<template_name> application that @gyorgybalazsi started off with. Why would I not define query within class ActionTriggerAny here?
I’m not sure what you’re getting at, tbh?
You couldn’t define query at least in the same way as it is in your example, i.e.
class ActionTriggerAny m where
query : forall a m . (Template a, ActionTriggerAny m) => m [(ContractId a, a)]
-- ^ m is defined twice!
because the m parameter is declared as a class-level (for lack of a better term) variable. So you would be trying to declare m twice. But this could be worked around by just dropping the m type constraint, as you’ve done?
Or is it somehow related to the inference of m? So that it’s lost and can’t be “type applied” when it’s declared at the class level? i.e. I couldn’t write implQuery @MyTemplate @Script for example? Just guessing here, I really don’t know

For class methods, you can’t explicitly quantify over the variables bound in the class head and those variables always come before the ones you quantify over in the method. So in this example, m would be before a which is not what you want for type applications.
The same visible type application is used with the query function in Triggers as well:
subscribers : [(ContractId Subscriber, Subscriber)] <- query @Subscriber
originals : [(ContractId Original, Original)] <- query @Original
copies : [(ContractId Copy, Copy)] <- query @Copy
See: Daml Triggers - Off-Ledger Automation in Daml — Daml SDK 1.10.0 documentation
And for the query function for triggers:
https://docs.daml.com/triggers/api/Daml-Trigger.html#function-daml-trigger-query-2759