docs: def grok(cls, value, value_type, visitor):
          """Like :py:meth:`normalize.visitor.VisitorPattern.unpack` but called
          for ``cast`` operations.  Expects to work with dictionaries and lists
          instead of Record objects.
  
          Reverses the transform performed in
          :py:meth:`normalize.visitor.VisitorPattern.reduce` for collections with
          properties.
  
          If you pass tuples to ``isa`` of your Properties, then you might need
          to override this function and throw ``TypeError`` if the passed
          ``value_type`` is not appropriate for ``value``.
          """
          is_coll = issubclass(value_type, Collection)
          is_record = issubclass(value_type, Record) and any(
              not visitor.is_filtered(prop) for prop in
              value_type.properties.values()
          )
  
          if is_record and not isinstance(value, cls.grok_mapping_types):
              raise exc.VisitorGrokRecordError(
                  val=repr(value),
                  record_type=value_type,
                  record_type_name=value_type.__name__,
                  field_selector=visitor.field_selector,
              )
  
          values = value
          if is_coll and is_record:
              try:
                  if "values" in value:
                      values = value['values']
              except TypeError:
                  pass
  
          generator = None
          if is_coll:
              if not isinstance(values, cls.grok_coll_types):
                  raise exc.VisitorGrokCollectionError(
                      val=repr(values),
                      record_type=value_type,
                      record_type_name=value_type.__name__,
                      field_selector=visitor.field_selector,
                  )
              generator = value_type.coll_to_tuples(values)
  
          propget = None
          if is_record:
              def propget(prop):
                  return value[prop.name]
  
          return propget, generator