Skip to content

Instantly share code, notes, and snippets.

@mezzomondo
Last active May 21, 2019 09:32
Show Gist options
  • Save mezzomondo/51c51e36922b5c9847b5380a272782e9 to your computer and use it in GitHub Desktop.
Save mezzomondo/51c51e36922b5c9847b5380a272782e9 to your computer and use it in GitHub Desktop.
Datatypes (attr), sum types (sumtypes) and pattern matching (pampy) in Python 3.7
from attr import attrs, attrib, validators
from sumtypes import sumtype, constructor
from pampy import match
from typing import Any, Dict
@attrs
class Valid:
valid_id: int = attrib()
valid_description: str = attrib()
valid_content: Dict[str, Any] = attrib()
@sumtype
class Maybe:
Just = constructor(valid=attrib(validator=validators.instance_of(Valid)))
Nothing = constructor()
def useless(i: int) -> Maybe:
if i > 3:
return Maybe.Just(Valid(i, 'test', {'a': i, 'b': 'nope'}))
# throws a TypeError: return Maybe.Just(1)
return Maybe.Nothing()
def what_is(x: Maybe) -> str:
return match(x,
Maybe.Just, 'Just ' + repr(x),
Maybe.Nothing, 'Nothing')
if __name__ == '__main__':
just_i = useless(4)
nothing = useless(1)
print(what_is(just_i))
print(what_is((nothing)))
@mezzomondo
Copy link
Author

More idiomatic:

from dataclasses import dataclass, field
from pampy import match
from typing import Any, Dict


@dataclass
class Valid:
    valid_id: int = 0
    valid_description: str = 'Nothing'
    valid_content: Dict[str, Any] = field(default_factory=dict)


@dataclass
class Just(Valid):
    tag: str = 'Just'


@dataclass
class Nothing(Valid):
    tag: str = 'Nothing'


def useless(i: int) -> Valid:
    if i > 3:
        return Just(i, 'test', {'a': i, 'b': 'nope'})
    return Nothing()


def what_is(x: Valid) -> str:
    return match(x,
                 Just, repr(x),
                 Nothing, 'Nothing')


if __name__ == '__main__':
    just_i = useless(4)
    nothing = useless(1)
    print(what_is(just_i))
    print(what_is((nothing)))

@mezzomondo
Copy link
Author

mezzomondo commented May 21, 2019

Even more idiomatic:

from dataclasses import dataclass
from pampy import match
from typing import Any, Dict


@dataclass
class MaybeValid:
    pass


@dataclass
class Just(MaybeValid):
    valid_id: int
    valid_description: str
    valid_content: Dict[str, Any]


@dataclass
class Nothing(MaybeValid):
    pass


def useless(i: int) -> MaybeValid:
    if i > 3:
        return Just(i, 'test', {'a': i, 'b': 'nope'})
    return Nothing()


def what_is(x: MaybeValid) -> str:
    return match(x,
                 Just, repr(x),
                 Nothing, 'Nothing')


if __name__ == '__main__':
    just_i = useless(4)
    nothing = useless(1)
    print(what_is(just_i))
    print(what_is((nothing)))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment