Remix.run Logo
▲ Fluorescence an hour ago

Not sure switching between languages makes for a compelling argument:

"Look how easy it is to accidentally bypass the invariant of a rust newtype by transliterating the data shape into Haskell and deriving a new type". Uh, ok.

If comparing the "risk of accident" between a newtype wrapper whose only role is enforcing the the invariant versus manually reimplementing vector and iterator semantics to use a different layout... I'd say the newtype wins that.

It would be good advice to keep a newtype that enforces an invariant as a single purpose primitive type. A building block and not a place to add other features.

There might be times I'd prefer structural enforcement e.g. something serialisation related. Converting into a non-rust format is what they are doing in their "accident"!