The current syntax for Callable types is unwieldy, particularly when extended to include varargs and keyword args as in http://mypy.readthedocs.io/en/latest/kinds_of_types.html#extended-callable-types. Why not introduce a signature literal? Proposed syntax: 

>>> from inspect import Signature, Parameter
>>> () ->
Signature()
>>> (arg0, arg1, arg2=None, arg3=None) ->
Signature(
    [Parameter('arg0', Parameter.POSITIONAL_OR_KEYWORD),
     Parameter('arg1', Parameter.POSITIONAL_OR_KEYWORD), 
     Parameter('arg2', Parameter.POSITIONAL_OR_KEYWORD, default=None),
     Parameter('arg3', Parameter.POSITIONAL_OR_KEYWORD, default=None)],
    return_annotation=str
)
>>> (arg0, arg1: int, arg2=None, arg3: float=None) -> str
Signature(
    [Parameter('arg0', Parameter.POSITIONAL_OR_KEYWORD),
     Parameter('arg1', Parameter.POSITIONAL_OR_KEYWORD, annotation=int), 
     Parameter('arg2', Parameter.POSITIONAL_OR_KEYWORD, default=None),
     Parameter('arg3', Parameter.POSITIONAL_OR_KEYWORD, annotation=float, default=None)],
    return_annotation=str
)
>>> (:, :, :, arg1, *, arg2) ->
Signature(
    [Parameter('', Parameter.POSITIONAL_ONLY),
     Parameter('', Parameter.POSITIONAL_ONLY),
     Parameter('', Parameter.POSITIONAL_ONLY),
     Parameter('arg1', Parameter.POSITIONAL_OR_KEYWORD), 
     Parameter('arg2', Parameter.KEYWORD_ONLY)]
)
>>> (:int, :float, *, keyword: complex) -> str
Signature(
    [Parameter('', Parameter.POSITIONAL_ONLY, annotation=int),
     Parameter('', Parameter.POSITIONAL_ONLY, annotation=float), 
     Parameter('keyword', Parameter.KEYWORD_ONLY, annotation=complex)],  
    return_annotation=str
)

Compare the above to their equivalents using Callable (and the experimental extension to Mypy):

>>> Callable[[], Any]
>>> Callable[[Arg(Any, 'arg0'), Arg(int, 'arg1'), DefaultArg(Any, 'arg2'), DefaultArg(float, 'kwarg3')], str]
>>> Callable[[Arg(), Arg(), Arg(), Arg(Any, 'arg1'), NamedArg(Any, 'arg2')], Any]
>>> Callable[[int, float, NamedArg(complex, 'keyword')], Any]

The proposed signature literal syntax is shorter, just as clear and imo nicer to read.

Here is what it looks like in annotations:

from typing import TypeVar, Callable 

A = TypeVar('A') 
def apply_successor(func: Callable[[A], A], init: A, n_applications: int) -> A: ...
def apply_successor(func: (:A) -> A, init: A, n_applications: int) -> A: ...

import tensorflow as tf
import numpy as np

def run(policy: Callable[[np.ndarray, Arg(Dict[tf.Tensor, np.ndarray], 'updated_feeds')], np.ndarray]) -> bool: ...
def run(policy: (:np.ndarray, updated_feeds: Dict[tf.Tensor, np.ndarray]) -> np.ndarray) -> bool: ...  
# If Mypy accepted literals for container types (dict, set, list, tuple, etc) this would be nicer still
def run(policy: (:np.ndarray, updated_feeds: {tf.Tensor: np.ndarray}) -> np.ndarray) -> bool: ...
 

Initial thoughts:
  • () -> is ugly, but the -> would be necessary to distinguish it from the empty tuple (). Actually, it can be difficult to tell the difference between the proposed signature literals and tuples, especially for long signatures with no annotations or defaults. An alternative would be to prefix the arguments with an @ or other uncommon symbol (maybe &). () -> becomes @(), and it is clear from the start that you're reading a signature.
  • Supposing the syntax for function definitions was changed to match the proposed signature literals, one could make something like the following possible:

    >>> def add(:, :):
    ...     arg0, arg1 = __call_signature__.args
    ...     return arg0.value + arg1.value
    >>> add(1, 2)
    3
    >>> add('hello', 'world')
    'helloworld'


    Where __call_signature__ is a magic name that evaluates to an inspect.BoundArguments instance representing the signature of the function call. I'm not sure why you'd want functions with positional-only arguments, but now you could have them.
  • You could further extend the function definition syntax to allow an expression that evaluates to a signature instead of a literal

    >>> signature = (:, :) ->
    >>> def add signature:
    ...     arg0, arg1 = __call_signature__.args
    ...     return arg0 + arg1


    Again, not sure how useful this would be.