You don’t need a Monad
instance; you can write things like
baz :: Int
baz = do 5
I guess that if you don’t try to compose or sequence “statements”, the instance is not required at all.
In fairness, we are just used to read “$” as deliminator, nothing readable about it neither. When I first started Haskell, it was shockingly alien too.
Also, the “true” type of $
is kind of hairy:
($) :: forall (r :: GHC.Types.RuntimeRep) a (b :: TYPE r). (a -> b) -> a -> b
Upon reflection, it feels odd to deploy an operator with such a complex type out of mere syntactic convenience.