Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idea: add Char type to represent Text with size = 1 #510

Open
yegle opened this issue Dec 6, 2017 · 3 comments
Open

Idea: add Char type to represent Text with size = 1 #510

yegle opened this issue Dec 6, 2017 · 3 comments
Labels
topic: feature Discussions about new features for Python's type annotations

Comments

@yegle
Copy link

yegle commented Dec 6, 2017

Due to the lack of character type in Python, a function that accept List[Text] will need to be extra careful when generalize the accepted argument type. Iterable[Text] and Sequence[Text] clearly doesn't work:

In [1]: import collections.abc

In [2]: isinstance("foo", collections.abc.Sequence)
Out[2]: True

In [3]: isinstance("foo", collections.abc.Iterable)
Out[3]: True

The closest thing you can do is to do something like Union[List[Text], Set[Text], Tuple[Text]] but it will not work with things like KeysView.

How about having a typing.Char to represent Text with length=1, and dedicate Text to a type with at least 2 characters?

Some examples to illustrate the usage:

def foo(xs: Iterable[Text]):
  return '|'.join(xs)

# list(Text) should return List[Char]
foo("abcd") # error
foo(list("abcd")) # correct, List[Char] is a special case of List[Text]

def bar(xs: Iterable[Char]):
  return '|'.join(xs)

bar("abcd") # correct, Text is a Iterable[Char]
bar(list("abcd")) # correct, List[Char] is a Iterable[Char]
bar(["ab", "cd"]) # error, List[Text] is not a Iterable[Char]

a: Char = 'a'

a[1] # error, Char cannot be indexed beyond index 0
a[0] # should be an error from type checking's PoV, Char should never be indexed
a[:] # should be an error from type checking's PoV, Char should never be copied as a slice

b: Text = 'b'
a + b # should be an error from type checking's PoV, Char and Text should be considered incompatible types
typing.cast(Text, a) + b # correct

c = a + a # correct, concatenate Char gets Text (but I'm not sure if this is reasonable though, what if we do (a + a) + a ?)
@ilevkivskyi
Copy link
Member

It is actually an interesting idea to have typing.Char as a string of length one. But for backwards compatibility we need to accept Char where Text is expected. I would recommend discussing this issue also on mypy tracker https://github.com/python/mypy

@srittau
Copy link
Collaborator

srittau commented Nov 4, 2021

Related: #256

@srittau srittau added topic: feature Discussions about new features for Python's type annotations and removed enhancement labels Nov 4, 2021
@sobolevn
Copy link
Member

sobolevn commented Nov 4, 2021

You can use phantom-types in this case: https://github.com/antonagestam/phantom-types/

from phantom.sized import PhantomSized

class Char(PhantomSized[str], str, len=1):
   ...

assert isinstance('a', Char) is True
assert isinstance('123', Char) is False

def works_with_char(c: Char): ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: feature Discussions about new features for Python's type annotations
Projects
None yet
Development

No branches or pull requests

4 participants