We override this method to do just one thing on top of ``ApplicationExpression._set_type``.
        In lambda expressions of the form /x F(x), where the function is F and the argument is x,
        we can use the type of F to infer the type of x. That is, if F is of type <a, b>, we can
        resolve the type of x against a. We do this as the additional step after setting the type
        of F(x).

        So why does NLTK not already do this? NLTK assumes all variables (x) are of type entity
        (e).  So it does not have to resolve the type of x anymore. However, this would cause type
        inference failures in our case since x can bind to rows, numbers or cells, each of which
        has a different type. To deal with this issue, we made X of type ANY_TYPE. Also, LambdaDCS
        (and some other languages) contain a var function that indicate the usage of variables
        within lambda functions. We map var to V, and made it of type <#1, #1>. We cannot leave X
        as ANY_TYPE because that would propagate up the tree. We need to set its type when we have
        the information about F. Hence this method. Note that the language may or may not contain
        the var function. We deal with both cases below.

def _set_type(self, other_type: Type = ANY_TYPE, signature=None) -> None:
        """
        We override this method to do just one thing on top of ``ApplicationExpression._set_type``.
        In lambda expressions of the form /x F(x), where the function is F and the argument is x,
        we can use the type of F to infer the type of x. That is, if F is of type <a, b>, we can
        resolve the type of x against a. We do this as the additional step after setting the type
        of F(x).

        So why does NLTK not already do this? NLTK assumes all variables (x) are of type entity
        (e).  So it does not have to resolve the type of x anymore. However, this would cause type
        inference failures in our case since x can bind to rows, numbers or cells, each of which
        has a different type. To deal with this issue, we made X of type ANY_TYPE. Also, LambdaDCS
        (and some other languages) contain a var function that indicate the usage of variables
        within lambda functions. We map var to V, and made it of type <#1, #1>. We cannot leave X
        as ANY_TYPE because that would propagate up the tree. We need to set its type when we have
        the information about F. Hence this method. Note that the language may or may not contain
        the var function. We deal with both cases below.
        """
        super(DynamicTypeApplicationExpression, self)._set_type(other_type, signature)
        # TODO(pradeep): Assuming the mapping of "var" function is "V". Do something better.
        if isinstance(self.argument, ApplicationExpression) and str(self.argument.function) == "V":
            # pylint: disable=protected-access
            self.argument.argument._set_type(self.function.type.first)
        if str(self.argument) == "X" and str(self.function) != "V":
            # pylint: disable=protected-access
            self.argument._set_type(self.function.type.first)