Я пытаюсь написать декодер JSON на Python, используя функциональное программирование, которое возвращает общий результат, а не выдает ошибки. Я считаю, что проблема связана с тем, что mypy думает, что базовая структура данных может в какой-то момент измениться в будущем, и использование «коварианта» устраняет проблему, но mypy жалуется на то, что ковариант является параметром.
Может ли кто-нибудь взглянуть на следующий код и ошибку mypy и объяснить, почему это происходит, как можно проще, и как я могу изменить код, чтобы устранить ошибки, сохраняя при этом неизменяемые классы данных?
Код: Выделить всё
from dataclasses import dataclass
from typing import Literal
@dataclass(frozen=True)
class Ok[T]:
value: T
@dataclass(frozen=True)
class Err[E]:
value: E
type Result[T, E] = Ok[T] | Err[E]
@dataclass(frozen=True)
class Dog:
nm: str
kind: Literal['Dog'] = 'Dog'
@dataclass(frozen=True)
class Cat:
nm: str
kind: Literal['Cat'] = 'Cat'
type Animal = Dog | Cat
def decodeDog(slop: dict) -> Result[Dog, str]:
try:
return Ok(Dog(slop["nm"]))
except Exception as e:
return Err(f"Decode Error: {e}")
def decodeCat(slop: dict) -> Result[Cat, str]:
try:
return Ok(Cat(slop["nm"]))
except Exception as e:
return Err(f"Decode Error: {e}")
def decodeAnimal(slop: dict) -> Result[Animal, str]:
match slop.get("kind"):
case "Dog":
return decodeDog(slop)
case "Cat":
return decodeCat(slop)
case _:
return Err("Unknown Animal")
if __name__ == "__main__":
print(decodeDog({"nm": "Spot"}))
print(decodeDog({"someOtherField": "someOtherStuff"}))
print(decodeCat({"nm": "Garfield"}))
print(decodeCat({"someOtherField": "someOtherStuff"}))
print(decodeAnimal({"nm": "Spot", "kind": "Dog"}))
print(decodeAnimal({"nm": "Garfield", "kind": "Cat"}))
print(decodeAnimal({"nm": "ET", "kind": "Animal"}))
Код: Выделить всё
❯ python example.py
Ok(value=Dog(nm='Spot', kind='Dog'))
Err(value="Decode Error: 'nm'")
Ok(value=Cat(nm='Garfield', kind='Cat'))
Err(value="Decode Error: 'nm'")
Ok(value=Dog(nm='Spot', kind='Dog'))
Ok(value=Cat(nm='Garfield', kind='Cat'))
Err(value='Unknown Animal')
Код: Выделить всё
example.py:42: error: Incompatible return value type (got "Ok[Dog] | Err[str]", expected "Ok[Dog | Cat] | Err[str]") [return-value]
example.py:44: error: Incompatible return value type (got "Ok[Cat] | Err[str]", expected "Ok[Dog | Cat] | Err[str]") [return-value]
Подробнее здесь: https://stackoverflow.com/questions/798 ... value-type
Мобильная версия