Lift Monoid to tagged value

37 views
Skip to first unread message

Parakhonskiy Gleb

unread,
Sep 25, 2016, 12:35:17 PM9/25/16
to scalaz
Hi everyone,
I suggest to add such thing to Monoid object. Basically it gives you a monoid for a tagged type, given a monoid for this type. I found it quite useful,
and if you think that it makes sense, I can make PR.



implicit def monoidOfTagged[T, A](implicit M0: Monoid[A]): Monoid[A @@ T] = new Monoid[@@[A, T]] {
  override def zero: @@[A, T] = Tag.of[T](M0.zero)

override def append(f1: @@[A, T], f2: @@[A, T]): @@[A, T] =
Tag.of[T](M0.append(Tag.unwrap(f1), Tag.unwrap(f2)))
}



And one more suggestion.
You can always take out function from Monad - if it returns the value inside this Monad:

def ???[A, B, F[_]: Monad](f: F[A F[B]]): A F[B] = a {
Monad[F].bind(f)(ff ff(a))
}

It just feels a bit weird to have such high level function laying in the Utils. I did not find such thing in scalaZ, so may be it makes sense to add it as well.


Thanks for a great library!
Cheers,
Gleb




Chris Marshall

unread,
Sep 26, 2016, 3:28:57 AM9/26/16
to sca...@googlegroups.com
This is specifically not useful. In scalaz, we may use tags to get a *different* monoid:

Monoid[Int @@ Multiplication]
Monoid[Boolean @@ Conjunction]

Being two obvious examples. I think scalaz should roll with a non implicit conversion you can use when you definitely want it, or possibly have a separate tag annotation for those tags which are not meant to incur such different ops

Chris 
--
You received this message because you are subscribed to the Google Groups "scalaz" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scalaz+un...@googlegroups.com.
To post to this group, send email to sca...@googlegroups.com.
Visit this group at https://groups.google.com/group/scalaz.
For more options, visit https://groups.google.com/d/optout.

Stephen Compall

unread,
Sep 26, 2016, 3:45:29 AM9/26/16
to sca...@googlegroups.com, Chris Marshall, Parakhonskiy Gleb
On September 26, 2016 2:28:53 PM GMT+07:00, Chris Marshall <oxbow...@gmail.com> wrote:
>I think scalaz should roll with a non
>implicit conversion you can use when you definitely want it,

Indeed, `Tag.subst` and TagOf#subst can do this already; for example, Gleb, you can write

implicit def monoidOfTagged[T, A](implicit M0: Monoid[A]): Monoid[A @@ T] = Tag.subst(M0)

subst is highly abstract and applicable in a huge variety of contexts; every on* function in Tag and everything else is just a specialization of subst or unsubst.
--
Stephen Compall
If anyone in the MSA is online, you should watch this flythrough.
Message has been deleted

Parakhonskiy Gleb

unread,
Sep 27, 2016, 3:34:07 AM9/27/16
to scalaz, oxbow...@gmail.com, parakh...@gmail.com
Right, that makes sense, and indeed 
implicit def monoidOfTagged[T, A](implicit M0: Monoid[A]): Monoid[A @@ T] = Tag.subst[A, Monoid, T](M0)

works perfectly.
 
Now, when I am thinking back, I realise, that at the beginning the goal was to apply binary operations on tagged values. For example you can add Kilogramms or Cms to each other, but you can not add Kg to Cm, so it should not compile. While tagging solves the second problem, the first one still remains (I think to #unwrap manually every time you wan to add two numbers - is not a real solution), so I thought to solve it with Monoid. But now I see, that it does not give you arithmetical operations at all, and moreover, this reasoning is only valid when Numbers are tagged. 

So actually, it makes sense to have this functionality on a Numeric typeclass (which is most likely noy the scalaZ domain): 
implicit def numericOfTagged[T, A: Numeric]: Numeric[A @@ T]
Reply all
Reply to author
Forward
0 new messages