Can someone explain what this bit of code does?

This function inserts Messages in a List of Messages. And if the Message already is in the list increases the Message counter.

So line by line:

insertM (M x1 x2 m) [] = [(x2, 1)] 

If the List is empty and you insert a Message, just enter the message with count 1.

insertM (M x1 x2 m) ((x22,k):t) = do

Thats the second case (look up pattern matching if you don't understand), where you insert a message, which looks like this (M x1 x2 m) into a list with the header (x22,k) and a tail t.

if x2 == x22 then 
    (x22, k+1):t

This lines checks if the part of the message x2is the same as the x22 of the first element of the list and the increments the counter. If this isn't the case you look up the rest of the list

  (x22, k): insertM (M x1 x2 m) t

(x22,k) is the head of the list, : appends two lists, insertM (M x1 x2 m) t is a recursive call on the tail where you lookup the rest of the list.

For example:

(insertM (M "A" "B" "chicken") [])         => [("B",1)]
(insertM (M "A" "B" "chicken") [("B",1)])  => [("B",2)]
(insertM (M "A" "C" "chicken") [("B",2)])  => [("B",2),("C",1)]

Any further questions?