Optimizing optimal reduction: A type inference algorithm for elementary affine logic