class_docstr: Type hint for :func:`make_funsor` decorated functions.
  
  This hint asserts that a set of :class:`Bound` variables
  always appear in the ``.inputs`` of the annotated argument.
  
  For example, we could write a named ``matmul`` function that
  asserts that both arguments always contain the reduced input,
  and cannot be constant with respect to that input::
  
      @make_funsor
      def MatMul(
          x: Has[{"i"}],
          y: Has[{"i"}],
          i: Bound,
      ) -> Fresh[lambda x: x]:
          return (x * y).reduce(ops.add, i)
  
  Here the string ``"i"`` in the annotations for ``x`` and ``y``
  refer to the argument ``i`` of our ``MatMul`` function,
  which is known to be ``Bound`` (i.e it does not appear in the
  ``.inputs`` of evaluating ``Matmul(x, y, "i")``.
  
  .. warning ::
  
      This annotation is experimental and may be removed in the future.
  
      Note that because Funsor is inherently extensional,
      violating a `Has` constraint only raises a :class:`SyntaxWarning`
      rather than a full :class:`TypeError`  and even then only under
      the :func:`~funsor.interpretations.reflect`  interpretation.
  
      As such, :class:`Has` annotations should be used sparingly,
      reserved for cases where the programmer has complete control
      over the inputs to a function and knows that an argument
      will always depend on a bound variable, e.g. when writing one-off
      Funsor terms to describe custom layers in a neural network.
  
  :param set bound: A :class:`~builtins.set` of strings of names of
      :class:`Bound` arguments of a :func:`make_funsor` -decorated function.
code: def __init__(self, bound):
      assert isinstance(bound, set)
      assert all(isinstance(v, str) for v in bound)
      self.bound = bound
  
imports: import inspect
  import typing
  import warnings
  from collections import OrderedDict
  from functools import singledispatch
  import makefun
  from funsor.instrument import debug_logged
  from funsor.terms import Funsor, FunsorMeta, Variable, eager, to_funsor
  from funsor.util import as_callable
label_desc: Use image node_id 1 to create a new Has object  with example: obj = Has(bound)