experimental implementation with monads
lazy evaluation