based on task from ICFP Programming Context 2012