from typing import Callable, Hashable, Sequence, Optional, Union, overload, TypeVar

_StringType = Sequence[Hashable]
S1 = TypeVar("S1")
S2 = TypeVar("S2")

@overload
def ratio(s1: _StringType, s2: _StringType, *, processor: Optional[bool] = None, score_cutoff: Optional[float] = 0) -> float: ...
@overload
def ratio(s1: S1, s2: S2, *, processor: Callable[[Union[S1, S2]], _StringType], score_cutoff: Optional[float] = 0) -> float: ...

@overload
def partial_ratio(s1: _StringType, s2: _StringType, *, processor: Optional[bool] = None, score_cutoff: Optional[float] = 0) -> float: ...
@overload
def partial_ratio(s1: S1, s2: S2, *, processor: Callable[[Union[S1, S2]], _StringType], score_cutoff: Optional[float] = 0) -> float: ...

@overload
def token_sort_ratio(s1: _StringType, s2: _StringType, *, processor: Optional[bool] = True, score_cutoff: Optional[float] = 0) -> float: ...
@overload
def token_sort_ratio(s1: S1, s2: S2, *, processor: Callable[[Union[S1, S2]], _StringType], score_cutoff: Optional[float] = 0) -> float: ...

@overload
def token_set_ratio(s1: _StringType, s2: _StringType, *, processor: Optional[bool] = True, score_cutoff: Optional[float] = 0) -> float: ...
@overload
def token_set_ratio(s1: S1, s2: S2, *, processor: Callable[[Union[S1, S2]], _StringType], score_cutoff: Optional[float] = 0) -> float: ...

@overload
def token_ratio(s1: _StringType, s2: _StringType, *, processor: Optional[bool] = True, score_cutoff: Optional[float] = 0) -> float: ...
@overload
def token_ratio(s1: S1, s2: S2, *, processor: Callable[[Union[S1, S2]], _StringType], score_cutoff: Optional[float] = 0) -> float: ...

@overload
def partial_token_sort_ratio(s1: _StringType, s2: _StringType, *, processor: Optional[bool] = True, score_cutoff: Optional[float] = 0) -> float: ...
@overload
def partial_token_sort_ratio(s1: S1, s2: S2, *, processor: Callable[[Union[S1, S2]], _StringType], score_cutoff: Optional[float] = 0) -> float: ...

@overload
def partial_token_set_ratio(s1: _StringType, s2: _StringType, *, processor: Optional[bool] = True, score_cutoff: Optional[float] = 0) -> float: ...
@overload
def partial_token_set_ratio(s1: S1, s2: S2, *, processor: Callable[[Union[S1, S2]], _StringType], score_cutoff: Optional[float] = 0) -> float: ...

@overload
def partial_token_ratio(s1: _StringType, s2: _StringType, *, processor: Optional[bool] = True, score_cutoff: Optional[float] = 0) -> float: ...
@overload
def partial_token_ratio(s1: S1, s2: S2, *, processor: Callable[[Union[S1, S2]], _StringType], score_cutoff: Optional[float] = 0) -> float: ...

@overload
def WRatio(s1: _StringType, s2: _StringType, *, processor: Optional[bool] = True, score_cutoff: Optional[float] = 0) -> float: ...
@overload
def WRatio(s1: S1, s2: S2, *, processor: Callable[[Union[S1, S2]], _StringType], score_cutoff: Optional[float] = 0) -> float: ...

@overload
def QRatio(s1: _StringType, s2: _StringType, *, processor: Optional[bool] = True, score_cutoff: Optional[float] = 0) -> float: ...
@overload
def QRatio(s1: S1, s2: S2, *, processor: Callable[[Union[S1, S2]], _StringType], score_cutoff: Optional[float] = 0) -> float: ...
