3 ms·
What's wrong with newtypes is that if you want to define "the monoid of integers under addition" and "the monoid of integers under multiplication" (or similar,
by joppy 5y ago
What's wrong with newtypes is that if you want to define "the monoid of integers under addition" and "the monoid of integers under multiplication" (or similar, the second isn't really a monoid because of zero), then an expression like a*x+b becomes some kind of newtype hell:
toAdditive ((toMultiplicative a) <> (toMultiplicative x)) <> toAdditive b
or something similar. This is of course an insane way to program, and so really what is done is that we define two entirely different operations of addition and multiplication so that they can be used without newtypes.
What would be cool is if operations could ad-hoc be bound to instances of typeclasses, for instance you could accumulate a list of integers inside the (0, +) monoid, or inside the (1, *) monoid. Of course this is basically what the fold functions in Haskell do, but you could imagine being able to formalise this pattern at the type level in a less newtype-hellish way.
- gugagore 5y agoI don't know why the Wikipedia article says otherwise, but 0 poses no problem for the integers to be a monoid under multiplication. Right? You just need an identity and associativity, not inverses.
- joppy 5y agoYeah you're totally right, my bad.
- greydius 5y ago> toAdditive ((toMultiplicative a) <> (toMultiplicative x)) <> toAdditive b > This is of course an insane way to program If you have a set with two binary operations, then a monoid isn't the correct abstraction. How would you propose to define <> so that a<>x<>b means ax+b and not e.g. a+xb. And how would your proposal be materially different from newtype conversions?
- joppy 5y ago> If you have a set with two binary operations, then a monoid isn't the correct abstraction. I guess my point is that even if I used "the correct abstraction" here, meaning a ring or something, then the whole newtype setup still makes it annoying for me to split off one operation and feed it into a function expecting a monoid: the way that fold and friends work is much more natural, just taking a starting value 1 and an operation * for example, rather than some kind of "Multiplicative" newtype or whatever. In general I see a lot of the abstract algebra type towers in Haskell and Purescript as being unhelpful, and making a huge assumption that (for example) there will rarely be two monoid instances on a type. In reality in abstract algebra we use tons of different operations on the same objects all the time, and I really just want to define those operations and then be able to use them.
- kccqzy 5y agoAn expression like a*x+b can be written that way directly. It's only when you need to take advantage of some folds do you really start using newtypes. And in Haskell you'd usually just do a coerce on an entire collection of them.