Personally, I believe Haskell syntax is a work of art. Learning how it fits together with currying is extremely satisfying. Also, the meaning of all the operators you mention, with the exception of (>>=), is immediately clear from their types.
(.) :: (b -> c) -> (a -> b) -> (a -> c)
It is clear that it takes two functions, and chains them together to create a new function
f . g = \x -> f (g x)
So
double (addOne 3)
is equivalent to
(double . addOne) 3
Similarly, (!!) has type
(!!) :: [a] -> Int -> a
It is immediately obvious from the type that it acceses the object at a particular index in a list, so
['a', 'b', 'c'] !! 1 == 'b'
Also, the syntax complements currying extremely well
f g h x
is equivalent to
(((f g) h) x)
This allows for some very neat things.
addOne :: Int -> Int
-- addOne 3 == 4
map :: (a -> b) -> ([a] -> [b]) -- which is equivalent to '(a -> b) -> [a] -> [b]'
map is an extremely neat function, and is used in many languages. It applies a function to every element of a list, producing a new list.
Note how map was partially applied. In Haskell, map can be seen as doing two things. One is taking a function and a list, and applying the function to every element in it to produce a new list. However, you can also see map as a function transformer, taking an ordinary function, and converting it into a function that works on lists!
map :: (a -> b) -> ([a] -> [b]) -- which is equivalent to '(a -> b) -> [a] -> [b]'
Now, there are two ways to use map
However, the above is equivalent to From this we see there is another way to use map Note how map was partially applied. In Haskell, map can be seen as doing two things. One is taking a function and a list, and applying the function to every element in it to produce a new list. However, you can also see map as a function transformer, taking an ordinary function, and converting it into a function that works on lists!