code: def find_common_type(dtypes):
      """
      Wrapper over np.find_common_type to handle special cases
  
      Corner cases:
      1. "M8", "M8" -> "M8" | "m8", "m8" -> "m8"
  
      Parameters
      ----------
      dtypes : iterable, sequence of dtypes to find common types
  
      Returns
      -------
      dtype : np.dtype optional, the result from np.find_common_type,
      None if input is empty
  
      """
  
      if len(dtypes) == 0:
          return None
  
      # Early exit for categoricals since they're not hashable and therefore
      # can't be put in a set.
      if any(
          cudf.api.types.is_categorical_dtype(dtype) for dtype in dtypes
      ):
          if all(
              (
                  cudf.api.types.is_categorical_dtype(dtype)
                  and (
                      not dtype.ordered
                      if hasattr(dtype, "ordered")
                      else True
                  )
              )
              for dtype in dtypes
          ):
              if (
                  len({dtype._categories.dtype for dtype in dtypes})
                  == 1
              ):
                  return cudf.CategoricalDtype(
                      cudf.core.column.concat_columns(
                          [dtype._categories for dtype in dtypes]
                      ).unique()
                  )
              else:
                  raise ValueError(
                      "Only unordered categories of the same underlying type "
                      "may be coerced to a common type."
                  )
          else:
              # TODO: Should this be an error case (mixing categorical with other
              # dtypes) or should this return object? Unclear if we have enough
              # information to decide right now, may have to come back to this as
              # usage of find_common_type increases.
              return cudf.dtype("O")
  
      # Aggregate same types
      dtypes = set(dtypes)
  
      if any(
          isinstance(dtype, cudf.core.dtypes.DecimalDtype)
          for dtype in dtypes
      ):
          if all(
              cudf.api.types.is_decimal_dtype(dtype)
              or cudf.api.types.is_numeric_dtype(dtype)
              for dtype in dtypes
          ):
              return _find_common_type_decimal(
                  [
                      dtype
                      for dtype in dtypes
                      if cudf.api.types.is_decimal_dtype(dtype)
                  ]
              )
          else:
              return cudf.dtype("O")
      if any(isinstance(dtype, cudf.ListDtype) for dtype in dtypes):
          if len(dtypes) == 1:
              return dtypes.get(0)
          else:
              # TODO: As list dtypes allow casting
              # to identical types, improve this logic of returning a
              # common dtype, for example:
              # ListDtype(int64) & ListDtype(int32) common
              # dtype could be ListDtype(int64).
              raise NotImplementedError(
                  "Finding a common type for `ListDtype` is currently "
                  "not supported"
              )
      if any(isinstance(dtype, cudf.StructDtype) for dtype in dtypes):
          if len(dtypes) == 1:
              return dtypes.get(0)
          else:
              raise NotImplementedError(
                  "Finding a common type for `StructDtype` is currently "
                  "not supported"
              )
  
      # Corner case 1:
      # Resort to np.result_type to handle "M" and "m" types separately
      dt_dtypes = set(
          filter(lambda t: cudf.api.types.is_datetime_dtype(t), dtypes)
      )
      if len(dt_dtypes) > 0:
          dtypes = dtypes - dt_dtypes
          dtypes.add(np.result_type(*dt_dtypes))
  
      td_dtypes = set(
          filter(lambda t: pd.api.types.is_timedelta64_dtype(t), dtypes)
      )
      if len(td_dtypes) > 0:
          dtypes = dtypes - td_dtypes
          dtypes.add(np.result_type(*td_dtypes))
  
      common_dtype = np.find_common_type(list(dtypes), [])
      if common_dtype == np.dtype("float16"):
          return cudf.dtype("float32")
      return cudf.dtype(common_dtype)
  
imports: import datetime
  from collections import namedtuple
  from decimal import Decimal
  import cupy
  import numpy
  import pandas
  import pyarrow
  from pandas.core.dtypes.common import infer_dtype_from_object
  import cudf
  from cudf._typing import DtypeObj
  from cudf.api.types import is_bool, is_float, is_integer
label_desc: Use image node_id 20 for calling a global function with example usage: find_common_type(dtypes) and returns: cudf, None, cudf, cudf, _find_common_type_decimal, cudf, dtypes, dtypes, cudf