I feel like this problem arises because Haskell has only one canonical instance of a typeclass per type. In Scala, Coq, Agda, etc. it’s much easier to talk about instances as ‘values’ of a record type that describes the shape of the algebraic structure in question - in the dependantly typed world it contains signatures for the laws as well. This has its own drawbacks though, both from a pedagogical and UX point of view. I would expand more, but alas I am typing this on an IPad whilst travelling abroad…

Edit: one way to look at it is that typeclasses like Monoid a are special record types (that live in a separate namespace in Haskell) that describe the shape that corresponding instances must conform to. Instances are singleton record values that conform to those special record types and are magically given names by the compiler, with a check to ensure they do not overlap with other instances.

This has its own drawbacks though, both from a pedagogical and UX point of view.

And refactoring. In Scala I always have to be careful about moving functions around to different modules. It’s stuff like “oh no, someone wrote their own Int Monoid and so my code broke”

Thinking about refactoring is the worst. You end up just leaving code being bad.

Oh, sure, IO afor a that forms a Monoid would be monoidal. Isn’t that just the case automatically by dint of being an applicative (since it’s a monad)? That’s how it tends to work in Scala.

Not really, at least that’s not the case in Haskell as far as I know. You’re right that since it’s a monad, it’s also an applicative functor (and a functor too) but you don’t need Monoid f for a Functor f instance, or for Applicative f for that matter. Check out Typeclassopedia if you like :)

I don’t think that there are any laws that ensure that with Monoid a and Applicative m you automatically get Monoid (m a), but can’t think of any examples off the top of my head. Also defining that instance means you can’t (or at least shouldn’t) define Monoid instances for anything which is a member of both classes. Generally instances of that sort (automatic based on a type being in these specific classes) seems like a good idea but actually isn’t.

The applicative laws are exactly the monoid laws. It creates an associative operation around an associative operation, so the laws are satisfied. This creates a useful type Ap:

It’s more like “Given Monoid a and Applicative f we can always construct a law-abiding Monoid (f a)”. We might not choose to actually have the instance reflected in code, but one is always there.

{-# language FlexibleInstances #-}
import Data.Monoid
import Control.Monad
import Control.Applicative
instance (Monoid a, Applicative m) => Monoid (m a) where
mempty = pure mempty
mappend = liftA2 mappend

Though in practice I’d use newtype Ap f m to avoid overlapping instances.

I feel like this problem arises because Haskell has only one canonical instance of a typeclass per type. In Scala, Coq, Agda, etc. it’s much easier to talk about instances as ‘values’ of a record type that describes the shape of the algebraic structure in question - in the dependantly typed world it contains signatures for the laws as well. This has its own drawbacks though, both from a pedagogical and UX point of view. I would expand more, but alas I am typing this on an IPad whilst travelling abroad…

Edit: one way to look at it is that typeclasses like

`Monoid a`

are special record types (that live in a separate namespace in Haskell) that describe the shape that corresponding instances must conform to. Instances are singleton record values that conform to those special record types and are magically given names by the compiler, with a check to ensure they do not overlap with other instances.And refactoring. In Scala I always have to be careful about moving functions around to different modules. It’s stuff like “oh no, someone wrote their own Int Monoid and so my code broke”

Thinking about refactoring is the worst. You end up just leaving code being bad.

How is

`IO`

a monoid? It’s not even the right kind, is it?`IO a`

is. It was proposed back in 2014 (Monoid instance for IO and discussion) and added in GHC 8:Relevant bit from Gabriel Gonzalez’s talk at LambdaConf: https://youtu.be/WsA7GtUQeB8?t=17m43s. That whole talk is pretty great by the way.

Oh, sure,

`IO a`

forwould be monoidal. Isn’t that just the case automatically by dint of being an applicative (since it’s a monad)? That’s how it tends to work in Scala.`a`

that forms a`Monoid`

Not really, at least that’s not the case in Haskell as far as I know. You’re right that since it’s a monad, it’s also an applicative functor (and a functor too) but you don’t need

`Monoid f`

for a`Functor f`

instance, or for`Applicative f`

for that matter. Check out Typeclassopedia if you like :)No I mean that

`Monoid a, Applicative m`

should imply`Monoid m a`

without needing to be a special case for`m = IO`

I don’t think that there are any laws that ensure that with Monoid a and Applicative m you automatically get Monoid (m a), but can’t think of any examples off the top of my head. Also defining that instance means you can’t (or at least shouldn’t) define Monoid instances for anything which is a member of both classes. Generally instances of that sort (automatic based on a type being in these specific classes) seems like a good idea but actually isn’t.

The applicative laws are exactly the monoid laws. It creates an associative operation around an associative operation, so the laws are satisfied. This creates a useful type

`Ap`

:https://hackage.haskell.org/package/reducers-3.12.1/docs/Data-Semigroup-Applicative.html

It’s more like “Given

`Monoid a`

and`Applicative f`

we can always construct a law-abiding`Monoid (f a)`

”. We might not choose to actually have the instance reflected in code, but one is always there.Sure. I was just playing around:

Though in practice I’d use

`newtype Ap f m`

to avoid overlapping instances.Nice reference to What We Talk About When We Talk about Love!