now handles failures, but I should probably read up on the error monad O_o