Denotational semantics are a great way to capture the meaning of a programming language. If your language provides a denotational semantics it's a nice exercise to implement them in a functional language. For instance, here's my implementation of R5RS Scheme in Haskell following the spec's semantics.[0]
A lot of toy Scheme implementations omit call/cc for instance because it can be hard to reason about and do correctly, whereas following the spec made it really easy.