Where communities thrive

  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
Repo info
Alexander Konovalov
Why? it's quite ingenious.
@Jacoby6000 I think even trait Forall[F[_]] { def apply[A]: F[A] } version is better than nothing.
Doesn't require a separate syntax import
Harrison Houghton
which trick gives you shame?
Jacob Barber
@alexknvl that's what I was leaning toward... But realistically that's so simple that I don't feel like it contributes much.
(unless it can start being applied to already existing parts of the codebase)

Hm... I know implicit conversions are bad, but is

implicit def forallA[F[_], A](forall: ForAll[F]): F[A] = forall.apply[A]


I imagine things would be weird whenever you start composing stuff
Jacob Barber
Applicative should be sufficient, i think.
Also, shouldn't it just be traverseWithIndex not traverseWithIndexM?
Alexander Konovalov
Curious thing. Given Mu[F] for some F, we can do only [A] (F[A] => A) => A. And AFAIU that should be enough to implement all possible operations on Mu[F]
I have no clue how to implement zip on two Mu[ListF[A, ?]] using only catamorphisms :smile:
Fabio Labella
re: fs2. It's not quite Free, the algebra is a bit more powerful. Also, most of the API is in final tagless style, so it's not necessarily a good example to see Free in action
Rob Norris
doobie is free but the interpreter is tagless so it's kind of weird. Also there are 14 algebras with 1000 constructors which presents some design challenges
Andy Scott
@Jacoby6000 the M suffix on traverseWithIndexM indicates that it requires G be a Monad.
I recall a discussion about trying to implement it with Applicative as the constraint… but it wasn’t possible AFAIK. Unless you do it in two passes over the structure F instead of one pass.
Jose Emilio Labra Gayo

One question, I found that the following code works

    type R1[A] = ValidatedNel[String,A]
    val i1 = implicitly[Applicative[R1]]

but the following one doesn't:

    type R2[A] = ValidatedNel[String,(A,A)]
    val i2 = implicitly[Applicative[R2]]
Is that right? I am using cats-1.0.0-MF
the error obtained with the second snippet is:
could not find implicit value for parameter e: cats.Applicative[R2]
Fabio Labella
@labra why do you need an instance of Applicative[R2]? If you have validated of tuples, that you can mapN with a function that takes tuples, the instance you need is ValidatedNel[String, A]
if instead you mapN with a function that operates on A (only operating on the second element of the tuple), you'd need something like Nested
Jose Emilio Labra Gayo
What surprises me is that if R1 compiles...why does R2 not?
I thought that if there was an applicative instance of ValidatedNel[String,A] then there was also an instance of ValidatedNel[String,(A,A)], but maybe I'm missing something...
Fabio Labella
it's different. Given that you have an instance for ValidatedNel[String, A] for all A, you can then instantiate the A type variable to any type, including (A, A). But the opposite is not true: if you look for ValidatedNel[String, (A, A)], ValidatedNel[String, A] does not apply.
you don't need ValidatedNel to show this, Option is enough
when you have (('a -> 1).some, ('b -> 2).some)).mapN { case ((x,y), (z,w)) => ???} the compiler looks for Applicative[Option[?]], and after finding it, instantiates the A (as in, there's an instance for Applicative[Option[A]] forall As), to Tuple2[Symbol, Int].
alternatively, you can say you're looking for ValidatedNel[String, (A, ?)], but that's different (and requires Nested)
Fabio Labella
I can explain it a bit better if you want
Fabio Labella

it's the difference between:

def foo[A]: Foo[A]


def foo2[A]: Foo[(A,A)]

where foo is implicit def applicativeForOption[A]: Applicative[Option[A]]

Fabio Labella

when you do implicitly[Applicative[R1]], you are saying, find me something of type [A] => Applicative[Option[A]] ; once you have this, you can specialise [A] to (B, B). Given the the instance for Option fits the shape [A] => Applicative[Option[A]], it compiles.
When you do implicitly[Applicative[R2]], you are saying, find me something of type [A] => Applicative[Option[(A,A]]. The instance for Option does not have this shape, so it doesn't compile.

* I'm using the fake type [A] => Foo[A] to represent polymorphic methods def foo[A]: Foo[A], Scala does not have first class polymorphic functions

Raphael Mäder
Hi everyone. I have this code in a unit test:
val m = mock[PageRepository[IO]].smart
m.tearDown returns IO { None }
and I get a codegen.java.lang.Object$MockitoMock$862296327 cannot be cast to cats.effect.IO exception. Does anyone know how to fix this? I'm quite new to cats and I'm unsure how to solve this, especially since the IO class is relatively new and I can't find anything about this issue on google :) thanks!
(the exception is thrown on the second line; stack trace doesn't provide more information)
Harrison Houghton
I'm not very experienced with Mockito, but I think you might be running into an issue with mock only getting the type PageRepository[_]
On account of erasure. Is that a scala mockito wrapper?
Raphael Mäder
Yes, from the Specs2 library. I'll read about type erasure, maybe I can find something. Thanks for the hint.
Harrison Houghton
Also, what is PageRepository?
If you're writing code that's parameterized over an arbitrary effect type, often you can make testing easier by replacing the effect with a less general one.
Alexandru Nedelcu
Hi folks, I need the Cats logo. Where can I find it?
Ian Macalinao
Can .map still be used on something with a Functor typeclass instance? Or do I need special imports for that syntax to work?
I'm no longer able to .map over something but if I do functor.map(thing)(fn) it compiles
Rob Norris
What is the type of thing and what cats imports do you have?
Normally you want cats.implicits._ and you want to compile with -Ypartial-unification
To get all the syntax
Fabio Labella
crucially, if you have cats.implicits._, you don't want to have any other implicit imports like syntax or instances @macalinao
Anatolii Kmetiuk

Hi all!

Can anyone explain me how Cats' Free Monad compares to Haskell's one?

Both in Scala and Haskell we seem to have Free programs as ASTs structures stored in memory during the runtime and executed by a separate instruction, usually involving an interpreter.

In Haskell, taking examples here, in order to run the free program, we appear to pass it to an interpreter function directly: one (interpreter is runGame), two (runWeb interpreter). In Scala, we need usually execute by calling a pre-defined interpret with the program and the interpreter, framework style.

In Haskell, the interpreters match on reifications of monad's methods: one, two (I am not very familiar with Haskell, but Return and :>>= look very much like their Pure and FlatMapped counterparts from Scala, correct me if I am wrong here). In Scala, it is in principle impossible to write an interpreter aware of these reifications, since they are private in Cats' implementation.

The Haskell versions make a lot of sense: you are able to define the semantics of the execution of the sequence of monadic method calls. In Cats, this semantics is pre-defined and final, and the emphasis is made on the semantics of individual statements. However, in the official tutorial, you can have the def program: KVStore[Option[Int]] = ... with the flexibility in put, update etc without free monads:

def program[F[_]: Monad](implicit ops: KvOps[F]) =
  for {
    _ <- ops.put("wild-cats", 2)
    _ <- ops.update[Int]("wild-cats", (_ + 12))

Where ops contains the same info as the interpreter, namely the implementation of the domain-specific methods. By switching F and the implicit parameter, you can execute the same program against many backends, with the same type safety as we had with free monads.

E.g. def impureCompiler: KVStoreA ~> Id = ... becomes:

implicit object IdOps extends KvOps[Id] {

  val kvs = mutable.Map.empty[String, Any]

  def put(k, v) = ...

Much less hassle, same effect (inspired by frees.io patterns).

My question is the following: is not the main power of a Free structure in that you are able to treat the sequence of monadic ops as a structure, and hence have perfect control on how to execute the structure? Is this not how Haskell does this (again, not very familiar with it, so I can be wrong here)? If so, why is the execution logic in Cats final, and the reification classes - private?

Fabio Labella
@anatoliykmetyuk You are looking at operational in Haskell, which is actually closer to Scala's version of Free than to the basic Haskell version