In the lattices, we have a number of methods to create ring structures from lattices. These seem like particular constructions to me, and perhaps not best bolted onto the traits themselves.
For instance, we could add:
trait Semigroup[T] {
//...
def asMonoid: Monoid[Option[T]]
}
which is a construction to create a Monoid from a semigroup using None as the unit, but I wouldn't want to do that. Similarly we can build a Ring[(BigInt, T)] from a Rng[T] by adding a 1 element and counting how many times it has been added (a: BigInt, t: T) = a * 1 + t, but again, that construction I would rather have a named class for that than bolt it onto the trait.
By contrast, .meetSemilattice is not a construction, it is exactly taking the meet and returning a Semilattice instance which combine == meet. This feels different to me.
Somewhat similarly is the .dual. Maybe we should have case class DualLattice[T](lattice: Lattice[A]) extends Lattice[A] or some such, instead of methods on the traits.