Yes, but I can't read other people's Haskell either.
In my specific sample above, the main understanding issue is that this isn't the "usual" BFS one might expect - e.g. it doesn't use a queue. And it doesn't operate node by node, but rather "layer by layer": in each recursion step it outputs all nodes reachable with a shortest path length of 0, then 1, then 2, then 3, ... (thus all those set operations). For trolling purposes, I evaded the typical queue a BFS would use.
Also, I had to use sets to not cause a worse than logarithmic (I know, fixable by using another Set implementation than Data.Set) complexity degradation. And to avoid having to decide on a specific representation of the graph, I just pass a function that from a node gives you the next nodes (which e.g. could be a map lookup).
Here's actually working code:
module Main where
import qualified Data.Set as S
bfs :: Ord a => (a -> S.Set a) -> S.Set a -> [S.Set a]
bfs getNext = bfs' getNext S.empty
bfs' :: Ord a => (a -> S.Set a) -> S.Set a -> S.Set a -> [S.Set a]
bfs' getNext visited current
| S.null current = []
| otherwise = (current : bfs' getNext visited' next)
where
visited' = visited `S.union` current
next = S.foldr (S.union . getNext) S.empty current `S.difference` visited'
graph :: Int -> S.Set Int
graph 0 = S.fromList [1, 2]
graph 1 = S.fromList [0, 3]
graph 2 = S.fromList [3]
graph 3 = S.fromList [4]
graph 4 = S.empty
main = print . bfs graph $ S.singleton 0