I repeat: the short circuit operations are associative,
so a && (b && c) necessarily has the same value and effects
as (a && b) && c. And this is just as true in C as in
Haskell. It is equally true in SML and Erlang (which
use andalso and orelse), Pascal Extended and Ada, OCaml
and F#, and Unix shells, to mention but a few.
Because the operations are associative, the associativity
of the operators is of no interest. Associativity is of
interest only when (a) there is more than one operator at
the same precedence level or (b) the operation is not
associative.
Your "training as a kid in math" almost certainly did not
include any discussion of logical operators, and I would
be astonished if you had been told that
a ** b ** c
was defined to be
a ** (b ** c)
back in 1950-something, or that there is a famous programming
language where A-B-C-D means A-(B-(C-D)) that is nearly as
old. Your "training as a kid in math" probably did not
include operators which are neither left associative nor
right associative but have a hidden conjunction, e.g.,
a <= b < c
does not, in a sane programming language (that is, a
language that is *not* C and didn't copy its blunders),
means a <= b && b < c (unless it is a syntax error).
Ada and SETLX do something interesting. They put
conjunction and disjunction at the same level, refuse
to define an associativity for them, and forbid mixing
them. That is, 'p and then q or else r' is simply not
legal in Ada.
Programming languages have done more and weirder things
with operators than you imagine. Take nothing for granted.