grayshadow's redo implementation in haskell