diff --git a/hwtypes/adt.py b/hwtypes/adt.py
index e65d70f..07abf20 100644
--- a/hwtypes/adt.py
+++ b/hwtypes/adt.py
@@ -78,9 +78,7 @@ class Product(Tuple, metaclass=ProductMeta):
 
 class Sum(metaclass=SumMeta):
     def __init__(self, value):
-        if not isinstance(value, tuple(type(self).fields)):
-            raise TypeError(f'Value {value} is not of types {type(self).fields}')
-        self._value = value
+        self.value = value
 
     def __eq__(self, other):
         return isinstance(other, type(self)) and self.value == other.value
@@ -95,6 +93,12 @@ class Sum(metaclass=SumMeta):
     def value(self):
         return self._value
 
+    @value.setter
+    def value(self, value):
+        if not isinstance(value, tuple(type(self).fields)):
+            raise TypeError(f'Value {value} is not of types {type(self).fields}')
+        self._value = value
+
     def match(self):
         return type(self.value), self.value
 
diff --git a/hwtypes/adt_meta.py b/hwtypes/adt_meta.py
index 489409a..5fab3ae 100644
--- a/hwtypes/adt_meta.py
+++ b/hwtypes/adt_meta.py
@@ -358,6 +358,28 @@ def __init__(self, {type_sig}):
         return cls.unbound_t.from_fields(cls.__name__, new_fields, cls.__module__, cls.__qualname__)
 
 class SumMeta(BoundMeta):
+    def __new__(mcs, name, bases, namespace, fields=None, **kwargs):
+        def _make_prop(field_type):
+            @TypedProperty(field_type)
+            def prop(self):
+                return self.value_dict[field_type.__name__]
+
+            @prop.setter
+            def prop(self, value):
+                self.value = value
+
+            return prop
+
+        if fields is not None:
+            for field in fields:
+                if field.__name__ in _RESERVED_NAMES:
+                    raise ReservedNameError(f'Field name {field.__name__} is reserved by the type machinery')
+                elif field.__name__ in namespace:
+                    raise TypeError(f'Field name {field.__name__} cannot be used as a class attribute')
+                namespace[field.__name__] = _make_prop(field)
+
+        return super().__new__(mcs, name, bases, namespace, fields, **kwargs)
+
     def _fields_cb(cls, idx):
         return frozenset(idx)
 

[feature-request] Access and modify Sum types by name (similar API to Product)
```
A = Sum[bool,int]
assert A.field_dict['bool'] == bool
assert A.field_dict['int'] == int

#I would like the following to work
assert hasattr(A,'bool')
assert hasattr(A,'int')
assert A.bool == bool
assert A.int == int
a = A(5)
assert a.int == 5
assert a.bool is None
a.int = 4
assert a.int == 4
try:
  a.bool = False
except:
  pass
else:
  assert 0
```
diff --git a/tests/test_adt.py b/tests/test_adt.py
index 6549226..ac577b7 100644
--- a/tests/test_adt.py
+++ b/tests/test_adt.py
@@ -170,12 +170,32 @@ def test_sum():
     assert isinstance(Su(En1.a), Su)
     assert isinstance(Su(En1.a), Sum)
 
+    assert Su.En1 == En1
+    assert Su.Pr == Pr
+
     assert Su.field_dict == {'En1' : En1, 'Pr' : Pr}
-    assert Su(En1.a).value_dict == {'En1' : En1.a, 'Pr' : None}
 
     with pytest.raises(TypeError):
         Su(1)
 
+    s = Su(En1.a)
+    assert s.value == En1.a
+    assert s.En1 == s.value
+    assert s.Pr is None
+    assert s.value_dict == {'En1' : En1.a, 'Pr' : None}
+
+    s.value = En1.b
+    assert s.value == En1.b
+    s.Pr = Pr(En1.a, En2.c)
+    assert s.value == Pr(En1.a, En2.c)
+    assert s.En1 is None
+    assert s.Pr == s.value
+
+    with pytest.raises(TypeError):
+        s.En1 = En2.c
+
+    with pytest.raises(TypeError):
+        s.Pr = En1.a
 
 def test_new():
     t = new(Tuple)

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y libgmp-dev libmpfr-dev libmpc-dev
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
exceptiongroup==1.2.2
gmpy2==2.2.1
-e git+https://github.com/leonardt/hwtypes.git@533beaabc2972e074c1b70dc213d38420ecd8cb8#egg=hwtypes
iniconfig==2.1.0
packaging==24.2
pluggy==1.5.0
PySMT==0.9.6
pytest==8.3.5
tomli==2.2.1
z3-solver==4.14.1.0

name: hwtypes
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - exceptiongroup==1.2.2
      - gmpy2==2.2.1
      - iniconfig==2.1.0
      - packaging==24.2
      - pluggy==1.5.0
      - pysmt==0.9.6
      - pytest==8.3.5
      - tomli==2.2.1
      - z3-solver==4.14.1.0
prefix: /opt/conda/envs/hwtypes

tests/test_adt.py::test_sum tests/test_adt.py::test_repr[Sum[Pr, tests/test_adt.py::test_unbound_t[Sum[Pr, tests/test_adt.py::test_rebind[Sum[Pr,
tests/test_adt.py::test_enum tests/test_adt.py::test_tuple tests/test_adt.py::test_product tests/test_adt.py::test_product_from_fields tests/test_adt.py::test_new tests/test_adt.py::test_repr[En1] tests/test_adt.py::test_repr[Tuple[En1, tests/test_adt.py::test_repr[Pr] tests/test_adt.py::test_reserved[field_dict-T_field0] tests/test_adt.py::test_reserved[field_dict-T_field1] tests/test_adt.py::test_reserved[value_dict-T_field0] tests/test_adt.py::test_reserved[value_dict-T_field1] tests/test_adt.py::test_reserved[fields-T_field0] tests/test_adt.py::test_reserved[fields-T_field1] tests/test_adt.py::test_reserved[value-T_field0] tests/test_adt.py::test_reserved[value-T_field1] tests/test_adt.py::test_reserved[enumerate-T_field0] tests/test_adt.py::test_reserved[enumerate-T_field1] tests/test_adt.py::test_reserved[is_bound-T_field0] tests/test_adt.py::test_reserved[is_bound-T_field1] tests/test_adt.py::test_unbound_t[En1-Enum] tests/test_adt.py::test_unbound_t[Pr-Product] tests/test_adt.py::test_unbound_t[Tuple[En1, tests/test_adt.py::test_rebind[Tuple[En1, tests/test_adt.py::test_rebind[Pr] tests/test_adt.py::test_rebind_recusrive
hwtypes/adt_meta.py hwtypes/adt.py
hwtypes/adt_meta.py hwtypes/adt.py