Maybe's Monoid instance, relation to Haskell's definition

elbear [9:08 AM]
I have a record with almost all fields having type Maybe a. I’m setting values for fields as I’m doing some checks. is there a way to start with an empty record or to have all fields set to Nothing without me doing that manually?
I can’t use a Map, because values have different types

goodacre.liam [9:11 AM]
@elbear you could start with an empty record and use
there’s also the Record.Builder module, if that’s applicable to your usecase

elbear [9:13 AM]
@goodacre.liam do you have a more concrete example of usage than the one in the documentation. I don’t undestand how I would use insert, just from that example
basically, I’m thinking of doing

# (\rec -> add label here)
# (\rec -> add another label)

goodacre.liam [9:15 AM]
yeah something like

{} # insert (SProxy :: SProxy "label0") (Just 42)

to give { label0: Just 42 } :: { label0 :: Maybe Int }

elbear [9:16 AM]
aha. ok, thanks!

i-am-tom [9:18 AM]
If you know the shape of the record ahead of time, mempty will also solve the problem of “how do I get all fields to set to Nothing unless I say otherwise”
You might need to use Last rather than Maybe, though, because the Monoid instance for Maybe is wrong (fight me @goodacre.liam)

goodacre.liam [9:20 AM]

joneshf [9:35 AM]
How is it still wrong?
I thought we learned from Haskell.
And I don’t mean, what makes it wrong.
But, why did we do the same thing as Haskell?

chexxor [9:41 AM]
What’s wrong?

elbear [9:42 AM]
maybe the Monoid instance for Maybe?

i-am-tom [9:43 AM]
Well well well
Haskell had instance Monoid a => Monoid (Maybe a)
and PureScript said this was nonsense, and went for instance Semigroup a => Monoid (Maybe a)
but in the McBride School of Monoids™, I put it to you that we should have instance Monoid (Maybe a) (edited)

goodacre.liam [9:44 AM]
(^ instance Monoid (Maybe a))

i-am-tom [9:44 AM]
Yes, thank you
allowing us to write a law like

  mempty = empty
  mappend = alt

which is true for lists, parsers, etc - basically everything but Maybe

joneshf [9:45 AM]
Wait, so we didn’t follow Haskell. We’re just wrong in a different way?

i-am-tom [9:45 AM]
Depending on who’s asking, yeah
McBride’s argument is that the Maybe type is meant to represent a computation that fails or aborts early. The current Monoid instance doesn’t fit that analogy

joneshf [9:46 AM]
What does the Semigroup instance look like?

i-am-tom [9:47 AM]
instance Semigroup (Maybe a) where append = alt (edited)

joneshf [9:47 AM]
And what does alt do?

i-am-tom [9:48 AM]

  Just x <> _ = Just x
  _      <> y = y

joneshf [9:48 AM]
Not trying to be difficult, but I thin there’s three implementations. So, looking for clarity. (edited)

i-am-tom [9:49 AM]
I think he normally phrases his dismay through the Dr Seuss parser example

type Parser a = String -> List (Tuple a String)

More importantly, “A parser of things is a function of strings to lists of pairs of things and strings
"I get alt for free with lists, but not with Maybe

joneshf [9:49 AM]
Is this the current instance for First _?

i-am-tom [9:49 AM]

joneshf [9:49 AM]

i-am-tom [9:49 AM]
though that should strictly be a semigroup

joneshf [9:49 AM]
And why don’t we want to do this?

i-am-tom [9:49 AM]
(and not a monoid)
history, I guess? It’s a departure from Haskell that is bound to upset people

joneshf [9:50 AM]
Does the Semigroup and Functor hierarchy have to interact in this way?

i-am-tom [9:50 AM]
I mean, none of them have to interact in any way, but we like laws
I suppose the answer is “apparently not” given that Conor never got his way

joneshf [9:51 AM]
What I’m getting at is that if this makes things more consistent, and we value consistency, we should make this change.

i-am-tom [9:52 AM]
cue @goodacre.liam

goodacre.liam [9:52 AM]
in some situations when we have two classes that we want to interact, we make a new sub class and attach the laws there

joneshf [9:53 AM]
Like Applicative, Bind, and Monad? (edited)

i-am-tom [9:53 AM]
More like BoundedEnum, I guess
class (Bounded a, Enum a) => BoundedEnum a
actually no, I’m probably talking rubbish - I think that one comes with functions too

goodacre.liam [9:53 AM]
class (EuclideanRing a, DivisionRing a) <= Field a (edited)

joneshf [9:54 AM]
Are you suggesting with create a new class instead of altering the current instances?

goodacre.liam [9:54 AM]
Not suggesting anything, just that it could be an option

joneshf [9:55 AM]

goodacre.liam [9:55 AM]
class (Alt a, Semigroup b) <= AltSemigroup (a b)
but yeah, my original argument when I first talked about this with Tom was that I can recover the First style instance by picking a different monoid, but not the other way around;
and that it wasn’t clear that the instances were supposed to interact as suggested,
there’s also the argument of not picking an instance when there are multiple sensible ones, etc
I’m not particularly tied to the current interpretation
:troll: what if Alt should have been

  alt :: Semigroup a => f a -> f a -> f a

sellout [10:15 AM]
What if Alt should have been Monoid?

joneshf [10:17 AM]

and that it wasn’t clear that the instances were supposed to interact as suggested,

I think I’m in this camp.
If it supposed to be this way, I’m all for it. But I don’t know if it is.

sellout [10:20 AM]
@joneshf you don’t need polykinds to eliminate Alt. It’s just a Monoid instance.

goodacre.liam [10:20 AM]
quantified constraints? :smile_cat:
(forall a . Monoid (Maybe a)) (edited)

sellout [10:21 AM]
I think … I sometimes mix up the different Alt-like names in different languages. But they mostly represent monoids in Set.

sellout [10:29 AM]
Any Alt instance on f can be rewritten as instance Monoid (f a) no?

Denis Stoyanov [10:32 AM]
I think maybe it will be like nearsemiring? (monadplus is nearsemiring in category of endofunctors)

i-am-tom [11:43 AM]
@sellout Yeah exactly, we can think of an Alt as “a semigroup that doesn’t care about the inner value”, I guess (edited)
m’colleague @blouerat beautifully terms it, “the universally-quantified semigroup” :

1 Like