3 ms·
What's "almost" algebraic about enum? It can definitely be used to construct sum types, and you can make product types with struct or inline in an enum
by leshow 7y ago
What's "almost" algebraic about enum? It can definitely be used to construct sum types, and you can make product types with struct or inline in an enum
- uryga 7y agomy best guess is that you can't do recursive enums without explicit boxing [edit: or other forms of indirection, like &T]¹. so you can't do this: enum List<T> { Nil, Cons(T, List<T>) } instead, you have to box/reference-ify the recursive occurrence: enum List<T> { Nil, Cons(T, Box<List<T>>) } so in certain circumstances it doesn't let you "coproduct" two types together, you might need to modify one a bit, which makes it a technically-not-exactly-a-coproduct (i think). a bit of a stretch but it sort of makes sense next to a by-reference-only ML langs where you can (co)product anything as you please (btw, it's the same for recursive products) --- 1 - https://users.rust-lang.org/t/recursive-enum-types/2938/2 https://users.rust-lang.org/t/recursive-enum-types/2938/2
- Ygg2 7y agoI think that's because Rust types are Sized, but I could be wrong. The first example has size = Infinity, while the second has a constant size.
- leshow 7y agoThanks for commenting, that's probably it. I was aware of the requirement for explicit box-ing but it didn't immediately come to mind.
- steveklabnik 7y agoYou don't have to box, but you do need some sort of type to make things sized. This is usually a pointer of some kind, but any kind of pointer works. Take references, for example: enum List<'a, T> { Nil, Cons(T, &'a List<'a, T>) } fn main() { let list = List::Cons("hello", &List::Nil); } Box is usually chosen because it's a good default choice.
- uryga 7y agoyou're right of course! i should've used a more generic term like "indirection" or "reference", didn't mean to put emphasis on Box
- steveklabnik 7y agoIt’s all good, most people say just Box, because it is the majority case.