Both ways presented in other answers at the moment (Enum.filter and --) will work well on small lists. But, lists are large, they are very inefficient.
If lists are large, better to use MapSet:
MapSet.difference(MapSet.new(a), MapSet.new(b)) |> MapSet.to_list
It spends some time to convert both lists to MapSets, and then to convert result back to list, but these operations are n log(n), while Enum.filter and substraction (--) here are quadratic.
I've prepared a gist with benchmarks.
Summary: for very short list substraction is fastest, for lists around 100 elements long Enum.filter is fastest, and for lists around 1000 elements MapSet.difference is fastest. It is hundreds times faster on lists with 100K elements.
Actually, on lists this size MapSet.difference works 0.08 seconds, Enum.filter 16 seconds, and substraction 44 seconds.
UPDATE: Dogbert asked me to also benchmark Erlang's ordsets:
:ordsets.subtract(:ordsets.from_list(a), :ordsets.from_list(b)) |> :ordsets.to_list
It works faster than MapSet, especially on mid-size lists about 1000 records long (MapSet is about 1.4 times slower).