why the question One may say that zip
is a method of Applicative
, the usual instance being ZipList
. I am unhappy with it because it is unsafe. I am unhappy with Align
too, because it is, by virtue of being all-encompassing, overly complicated and not specific enough for usual cases.
lawful classes Some type classes in Haskell may be dubbed lawful. This means that they come with equalities that must hold — the laws for a class. It is ordinary that these laws come from category theoretic conceptualization of an aspect of programming. For example, Monad
is a conceptualization of computations (whatever is meant by that) via the eponymous category theory device.
overlaying things The usual operation to want to do with boxes of things is to lay them on top of each other, and if they are monoid, they will meld.
Examples:
not enough laws The conceptualization of this concept is via monoidal functors, and the corresponding Applicative
type class. There is, however, an annoying complication in that there are very often two ways to define the Applicative
that both appear suitable. Why so? I propose that the answer is "not enough laws".
Examples:
For arithmetics:
- The
Sum
monoid is the actual "endo-monoid". It is only legal for kin things. You cannot sum mass and force, for instance. - The
Product
monoid takes numbers of dimensiona
&b
to a number of dimensionc
. Multiplying mass and force is legal and gets us to warmth.
So, the right choice of monoid may be inferred from types.
- The
For lists:
- The usual direct sum of lists is the more safe one. It works with any finite number of elements trivially, and with co-finite number thereof with a "diagonal process" definition such as LogicT.
- The
ZipList
definition is clearly unsafe. It is defined to, given two lists of distinct length, crop the longer one to the length of the shorter. - Length indexed vectors are the device that allows for a safe definition of
zip
, by demanding a proof that the given lists are of same length.
For matrices:
- The usual addition of matrices has the (very reasonable) requirement of dimension homogeneity, the same as with length indexed vectors mentioned above. Since matrices are habitually used in various real world simulations, such as 3D graphics, once matrices begin to get cropped or zero-padded, people would complain quite immediately, so a
ZipMatrix
definition along the lines ofZipList
above does not appear attractive. - The stranger Kronecker multiplication is reminiscent of the direct product of lists. And it admits the definition of
Monad
, too.
- The usual addition of matrices has the (very reasonable) requirement of dimension homogeneity, the same as with length indexed vectors mentioned above. Since matrices are habitually used in various real world simulations, such as 3D graphics, once matrices begin to get cropped or zero-padded, people would complain quite immediately, so a
two cases From these examples, it reveals itself that there are two distinct ideas mixed up in the thing we call a "monoid" or a "monoidal functor", and the distinction is very important for programming (unlike, perhaps, pure theory) because it would clean up confusion, remove unsafeties and, primarily, because there are, in each case, two completely unrelated algorithms to run.
I am thinking that maybe invertibility (also called "strength") of the monoidal functor is what matters. But the results of the Sum and the Product monoidal operation on Peano naturals are indistinguishable. (I am unsure whether they can be considered monoidal endofunctors.) So, I am turned to a guess that the changing of types is the hallmark. Multiplication of physical quantities does not type check as a Monoid
, even!
P.S. There presents itself an instance of Monad
for length indexed vectors over cartesian products and for matrices over Kronecker multiplication, with some sort of fold zip
as join
.
liftA2 (,) xs ys == liftA2 (,) xs' ys'
, thenxs == xs'
andys == ys'
". But the usualApplicative
instance for lists (which I think you're calling the "direct sum"), which you claim is invertible, does not satisfy this definition (e.g.liftA2 (,) [] [()] == liftA2 (,) [()] []
), so I'm unclear on exactly what you want here. (And this is not a quibble about emptiness: there are also non-empty lists which break invertibility.) – Daniel Wagnerzip
is a method ofApplicative
". Why? And all monids are "endo-monoids"; the definition starts with a single type and a closed binary operation on that type. – chepnerHask
understanding of "monoid" must be expanded. For instance, length indexed vectors are an obvious monoid, it is just that there is a type level (also monoidal) operation involved in the definition ofmappend
. Notice also that a monad is a monoid in the category of endofunctors. – Ignat Insarovzip
isliftA2 (,)
inControl.Appicative.ZipList
. Also, becauseApplicative
actually somewhat stands for "monoidal functor", and the definition thereof would strike you with its similarity to the type ofzip
. – Ignat Insarov(a -> b -> c) -> v n a -> v m b -> v (n * m) c
) and the zip kind ((a -> b -> c) -> v n a -> v n b -> v n c
), there is a contraction kind for matrices:Monoid c => (
a -> b -> c) -> m x y a -> m y z b -> m x z c`. That said I think the right place for this would be a shape-indexed applicative. This works for vectors which are obviously zippable and the size is easily expressed. It also works for functions. It doesn’t for maps. – Dan Robertson