Step <- function(fun, target_dims, output_dims, 
                 use_libraries = NULL, use_attributes = NULL) {
  # Check fun
  if (!is.function(fun)) {
    stop("Parameter 'fun' must be a function.")
  }

  # Check target_dims
  if (is.character(target_dims)) {
    target_dims <- list(target_dims)
    names(target_dims) <- 'input1'
  }
  if (is.list(target_dims)) {
    sapply(target_dims, 
      function(x) {
        if (!(is.character(x) && (length(x) > 0))) {
          stop("Parameter 'target_dims' must be one or a list of vectors ",
               "of target dimension names for each data array input in ",
               "the function 'fun'.")
        }
      })
    if (is.null(names(target_dims))) {
      names(target_dims) <- paste0('input', 1:length(target_dims))
    }
  }

  # Check output_dims
  if (is.character(output_dims) || is.null(output_dims)) {
    output_dims <- list(output_dims)
    names(output_dims) <- 'output1'
  }
  if (is.list(output_dims)) {
    sapply(output_dims, 
      function(x) {
        if (!(is.character(x) || is.null(x))) {
          stop("Parameter 'output_dims' must be one or a list of vectors ",
               "of target dimension names for each data array input in ",
               "the function 'fun'.")
        }
      })
    if (is.null(names(output_dims))) {
      names(output_dims) <- paste0('output', 1:length(output_dims))
    }
  }

  # Check use_libraries
  if (!is.null(use_libraries)) {
    if (!is.character(use_libraries)) {
      stop("Parameter 'use_libraries' must be a vector of character ",
           "strings.")
    }
  }

  # Check use_attributes
  if (!is.null(use_attributes)) {
    raise_error <- FALSE
    if (!is.list(use_attributes)) {
      raise_error <- TRUE
    }
    if (!all(sapply(use_attributes, 
        function(x) {
          is.character(x) ||
          (is.list(x) && all(sapply(x, is.character)))
        }))) {
      raise_error <- TRUE
    }
    if (raise_error) {
      stop("Parameter 'use_attributes' must be a list of vectors of ",
           "character strings or of lists of vectors of character ",
           "strings.")
    }
  }

  attr(fun, 'TargetDims') <- target_dims
  attr(fun, 'OutputDims') <- output_dims
  attr(fun, 'UseLibraries') <- use_libraries
  attr(fun, 'UseAttributes') <- use_attributes

  # TODO: Add provenance info
  class(fun) <- 'startR_step_fun'

  fun
}
