Here's a completely different, arguably even more hacky, but much simpler solution:
syntax keyword lam fn conceal cchar=λ containedin=ALL nextgroup=bda
execute "syntax match bda ' ' conceal cchar=\uff0e"
It relies on:
There always being a space after the fn keyword: we're matching this space as well as the fn.
Unicode support: we're replacing the space ...
Here's a solution using a different technique to the two you suggested:
syntax match lambda /\_.\<fn\>/ containedin=ALL
syntax match lam /f/ containedin=lambda contained conceal cchar=λ
syntax match bda /n/ containedin=lambda contained conceal cchar=.
Syntax items which start in an earlier position in the buffer take priority over other items, so we ...