These are chat archives for typelevel/cats

16th
Jul 2016
Rob Norris
@tpolecat
Jul 16 2016 05:07
What's the story for 2.12?
Adelbert Chang
@adelbertc
Jul 16 2016 07:04

@ceedubs so i noticed you started work on the separate type class default impl thing. i'm wdonering what you think of also moving implementations into public traits.. instead of

implicit def xorMonad[L]: Monad[L Xor ?] = new Monad[L Xor ?] { ... }

have

trait MonadXor[L] extends Monad[L Xor ?] { ... }

implicit def xorMonad[L]: Monad[L Xor ?] = new MonadXor[L]

This would allow for MTL-style programming, so if someone defined a subclass of monad..]

trait MonadFoo[F[_]] extends Monad[F] { ... }

then implementing that for say, Xor, only requires doing

trait MonadFooXor[L] extends MonadFoo[L Xor ?] with MonadXor[L] { /* implement only MonadFoo methods */ }
the general problem im trying to solve is not having to redefine Monad[F] for any F (if it already exists in Cats) if a subclass of Monad is made
Cody Allen
@ceedubs
Jul 16 2016 14:42
@tpolecat I was wondering about the 2.12 story the other day. I wasn’t sure whether all of Cats’ dependencies have been published for 2.12 yet. I personally don’t have a major rush for 2.12, so I was going to wait it out a bit until either a final 2.12 is published or Cats is ready for a 1.0 release to worry about it. But if someone wants a 2.12 version and is willing to make it happen, I’m all for that.
Request for feedback on whether type class traits should have default implementations of methods baked in: typelevel/cats#1194
@adelbertc as mentioned in that issue, there’s some discussion as to whether default implementations should be separated. But I think your question is somewhat orthogonal, and I don’t think I have any objection to making those traits public. It might mean being slightly more careful with compatibility, but that should be fine.
Rob Norris
@tpolecat
Jul 16 2016 14:47
@ceedubs it's more an issue of being prepared for 2.12 in case there are issues. cats uses a lot of machinery.
Cody Allen
@ceedubs
Jul 16 2016 14:48
@tpolecat ah yeah that’s a good point
TBH I thought 2.12 would be more stable by now. There are still some significant changes going in.
It’s @milessabin’s fault for fixing SI-2712 and getting people all riled up about making contributions :P
Rob Norris
@tpolecat
Jul 16 2016 14:51
doobie/scalaz/streams is on 2.10/11/12
doobie/cats/fs2 is 2.11 only
Which I realized last night and set off a slight panic.
Cody Allen
@ceedubs
Jul 16 2016 14:53
ah I see :\
Rob Norris
@tpolecat
Jul 16 2016 14:54
I'll look and see what's lacking.
Cody Allen
@ceedubs
Jul 16 2016 14:54
@tpolecat that would be wonderful. Thank you!
It’s definitely something that I would get to before trying to push a 1.0 release, but I think that it is something that would move a lot faster if someone else is driving it
Rob Norris
@tpolecat
Jul 16 2016 14:55
You're on 2.10 at work right?
Cody Allen
@ceedubs
Jul 16 2016 14:55
mostly 2.11 on newer projects but there’s still quite a bit of 2.10 code lying around
Rob Norris
@tpolecat
Jul 16 2016 14:56
Ok.
Cody Allen
@ceedubs
Jul 16 2016 14:56
we are cross-publishing a number of internal libraries to allow for that
"quite a bit of 2.10 code lying around” was probably an understatement :)
Rob Norris
@tpolecat
Jul 16 2016 14:57
fs2 doesn't do 2.10 and I know you do a lot of scalaz-streaming. So was curious how you'll deal with that.
I'll catch up with you or stew or someone later. Gotta run. Enjoy your Saturday!
Cody Allen
@ceedubs
Jul 16 2016 14:59
@tpolecat yeah I think older 2.10 code bases would probably just stay on scalaz-stream until they either went away or were ready for 2.11/2.12. Okay ttyl. Enjoy yours as well!
Shane Delmore
@ShaneDelmore
Jul 16 2016 19:18
Can anyone point me to an example of using cats.Monad to write a function that takes any monad? I am struggling to get the syntax correct.
Yilin Wei
@yilinwei
Jul 16 2016 19:19
@ShaneDelmore def identity[F[_]: Monad, A](fa: F[A]): F[A] = fa.map(identity)
Oh you should probably not call the function identity but something like identity2
Shane Delmore
@ShaneDelmore
Jul 16 2016 19:24
I am experimenting with loosening the specificity of monads I use. Simple version in this gist. For example, I would love if all of the Option references in this gist could be Monad, and I could swap out any of them. https://gist.github.com/ShaneDelmore/0484a81e93fdb7d8bddc3e54c377a4c3
Oops, didn't realize that would fill the screen.
Would I be able to add the Monad type to the trait as a function so I didn't have to change each function signature or is that just not how it works?
Yilin Wei
@yilinwei
Jul 16 2016 19:26
Yeah you can
trait UserRepos[F[_]] {
  implicit def F: Monad[F]
  def userRepo: UserRepo
  trait UserRepo {
    def followers(userId: Long): F[List[User]]
  }
}
Yilin Wei
@yilinwei
Jul 16 2016 19:27
You can also put the implicit/type constraint on the function itself
If you have functions which have less stringent requirements
Shane Delmore
@ShaneDelmore
Jul 16 2016 19:28
I'm looking for the least boilerplatey way of doing it. It just works if I leave off type annotations altogether, and have different implementations with no shared trait, so now I am trying to figure out the lightest way to add a shared trait for the implementations. Modifying each function to have an added implicit doesn't feel like what I am looking for.
But @eed3si9n links look pretty much like what I was after. Will experiment a bit. Thanks everyone!
Shane Delmore
@ShaneDelmore
Jul 16 2016 21:17
@eed3si9n I tried to follow along with your tutorial but transforming it to the original code I was experimenting with today, and have been unable to either make it work, or figure out how it differs from your tutorial. The goal all along has been to convince Scala that I have something with flatMap but after banging on it for a couple of hours I am still at "Error:(13, 26) value flatMap is not a member of type parameter F[repos.TokenLifetime]
loginTtl <- repo.validatedTokenLifetime"
Any hints on what I might be doing wrong? I pushed my code to https://github.com/ShaneDelmore/InsulatingBusinessLogic/blob/master/src/main/scala/domain/UserActions.scala if anyone is interested in taking a look. Feels like I am close, but missing one thing.
eugene yokota
@eed3si9n
Jul 16 2016 21:32

@ShaneDelmore I think I ran into similar issue:

It would be nice if I could use infix flatMap and map method while keeping F abstract. I tried creating FlatMapOps(fa) manually, but that resulted in abstract method error during runtime.

so I used actM macro
monad DSL similar to build.sbt:
      actM[F, Boolean] {
        val a = userRepo.followers(user1).next
        val b = userRepo.followers(user2).next
        a.exists(_.id == user2) && b.exists(_.id == user1)
      }
Shane Delmore
@ShaneDelmore
Jul 16 2016 21:34
Hmm.....I just did a terribly thing I sometimes do when working with cats....I just started importing things. Ended up importing cats.implicits._ and now Monad has flatMap. Seems maybe it isn't actually on Monad, just an implicit that works with Monad maybe?
eugene yokota
@eed3si9n
Jul 16 2016 21:36
i tried that a while back, so maybe it works with the latest
Shane Delmore
@ShaneDelmore
Jul 16 2016 21:36
Which means on the upside it works, but on the downside that does not leave me with a good feeling about recommending it to coworkers. I wish I could finally figure out how to easily troubleshoot implicits. Two year after starting with Spray I still have a hell of a time troubleshooting magnets. Seems I do similarly well with Cats. Such a great lib, so hard for me to troubleshoot.
Yeah...seems to if you know what to import. I usually do actually just import the world, but Intellij guys specifically called out Cats implicits as something they struggle with so I am trying to pull the world in less often so my IDE isn't quite so slow.
Yilin Wei
@yilinwei
Jul 16 2016 21:49
@ShaneDelmore, flatMap is from this file
There's also an alias object in general for each of the different typeclasses. If you're looking for a particular function just think of the typeclass that the function is part of and search for it under the syntax directory.
In core, some of these are generated by simulacrum.
If it isn't a syntax but rather an instance that you're trying to find, look in the companion object - unless it's a std class in which you should look under the instances (which used to be std) directory.
Shane Delmore
@ShaneDelmore
Jul 16 2016 21:52
I don't quite get the connection. Given that information, I would naively assume I should import cats.syntax.FlatMap. Or even cats.syntax., but neither of those work, while cats.implicits. does.
Also, cats.Monad._ didn't work (is that what you mean by the companion object in this case?).
Yilin Wei
@yilinwei
Jul 16 2016 21:53
cats.implicits._ just imports everything - it extends from the syntax.
Shane Delmore
@ShaneDelmore
Jul 16 2016 21:53
How would I determine the smallest thing I need to import to make this work?
Yilin Wei
@yilinwei
Jul 16 2016 21:55
The smallest thing which should give you a flatMap on a F[_] : Monad should be cats.syntax.flatmap._ which is defined in here
Shane Delmore
@ShaneDelmore
Jul 16 2016 21:56
Or, maybe to ask a different question....was basing this on Monad the wrong place to start. What I really wanted is something with flatMap defined, is there a FlatMappable typeclass that definitely has flatMap, without requiring any additional imports?
Yilin Wei
@yilinwei
Jul 16 2016 21:56
Yes, but the typeclass isn't on the object if you like.
i.e.
you can't call
fa.flatMap(f)
as @yilinwei has said, you need import cats.syntax.flatmap._ if you want to add a flatMap method onto types that have a Monad instance
alternatively you can do something like def foo[F[_]](fa: F[A])(implicit monadF: Monad[F]): F[A] = monadF.flatMap(fa)(_ => fa) or something like that
Shane Delmore
@ShaneDelmore
Jul 16 2016 21:58
That doesn't work for me, if I add import cats.syntax.flatMap. I get the same error, but cats.implicits. works.
Will give that a try, see if I like that better.
Yilin Wei
@yilinwei
Jul 16 2016 21:59
flatMap._
Cody Allen
@ceedubs
Jul 16 2016 21:59
you can call the method that exists on the Monad instance, but it’s more concise to use the import to enrich F[A] types with a flatMap method
Yilin Wei
@yilinwei
Jul 16 2016 21:59
And if you do get the error, I would suspect you have a conflicting import.
Cody Allen
@ceedubs
Jul 16 2016 21:59
@ShaneDelmore note that we are saying cats.syntax.flatMap._ (the trailing underscore)
and you will also need the Monad instance for your type in scope at the call site
so that might mean something like cats.std.option._ or cats.std.list._
Shane Delmore
@ShaneDelmore
Jul 16 2016 22:02
I see the trailing underscore, but it doesn't work. The specific case I am referring to is here: https://github.com/ShaneDelmore/InsulatingBusinessLogic/blob/master/src/main/scala/domain/UserActions.scala#L5
Yilin Wei
@yilinwei
Jul 16 2016 22:03
You need the type bound
It doesn't know that F[_] has a monad associated with it?
Shane Delmore
@ShaneDelmore
Jul 16 2016 22:04
I tried trait UserActions[F[_]: Monad] { this: UserRepo[F] => but results in compile error Error:(10, 32) traits cannot have type parameters with context bounds : ...' nor view bounds<% ...'
trait UserActions[F[_]: Monad] { this: UserRepo[F] =>
Yilin Wei
@yilinwei
Jul 16 2016 22:04
You can add implicit def M: Monad[F]
what does repo.validatedTokenLifetime return?
Shane Delmore
@ShaneDelmore
Jul 16 2016 22:06
I have that here: https://github.com/ShaneDelmore/InsulatingBusinessLogic/blob/master/src/main/scala/repos/UserRepo.scala#L14 Or are you saying I need to duplicate it in my UserActions trait even though it has self type of UserRepo?
F[TokenLifetime]
Yilin Wei
@yilinwei
Jul 16 2016 22:08
I'm not sure whether it needs it but if it does I'm surprised that implicits._ work. Try adding a dummy implementation to see whether it compiles.
Let me clone it to take a look.
Shane Delmore
@ShaneDelmore
Jul 16 2016 22:10
Not only does adding that not make it work, it has the odd effect of making the version with implicits._ no longer work. That was completely unexpected (to me).
Yilin Wei
@yilinwei
Jul 16 2016 22:11
Hmm that sounds like a transient issue with the incremental compile - gimme a sec to clone it down
Shane Delmore
@ShaneDelmore
Jul 16 2016 22:17
Thanks. I am going to try to present it at the next PDX Scala meetup....Will make sure to bring a picture of "I have no idea what I am doing" dog. I actually use a similar pattern all over our codebase now but don't actually specify the types, just let the compiler infer them which works fairly great. Just figured I should learn the right way finally :smile:
Yilin Wei
@yilinwei
Jul 16 2016 22:23
OK so basically there's an error when we moved off or onto simulacrum basically
@ShaneDelmore you need to add cats.syntax.functor._
Since the map isn't on the syntax
Shane Delmore
@ShaneDelmore
Jul 16 2016 22:25
Oh hey....that's great. Should I open a ticket on the need for the second import?
Yilin Wei
@yilinwei
Jul 16 2016 22:25
Opening one already
I want to sanity check some other stuff at the same time
but it's a little late at the moment
Shane Delmore
@ShaneDelmore
Jul 16 2016 22:26
I'm off to write some tests now that I understand better what is going on. Thank you so much for the explanations.
Yilin Wei
@yilinwei
Jul 16 2016 22:28
np, thank you for finding the bug!