Giter Club home page Giter Club logo

Comments (20)

non avatar non commented on July 22, 2024

I'm sympathetic to this. Would you mind pasting a simple example here (i.e. functor.Invariant[_]) just so we could see what it would look like?

EDIT: To be clear, I just want to see what trait InvariantLaws[F[_]] { ... } would look like.

from cats.

fthomas avatar fthomas commented on July 22, 2024

@non here is one way to do it: https://github.com/fthomas/cats/compare/wip/move-laws

from cats.

julien-truffaut avatar julien-truffaut commented on July 22, 2024

maybe it would read better if we would use syntax for laws?

from cats.

fthomas avatar fthomas commented on July 22, 2024

Updated the branch to use syntax for Eq. It looks a little bit better now.

from cats.

non avatar non commented on July 22, 2024

So here's one concern -- if the laws fail you probably get little or no useful output.

In algebra, we used the ?== operator to get output when the === tests fail. Here's the relevant code:

https://github.com/non/algebra/blob/master/laws/src/main/scala/algebra/laws/package.scala#L23

Obviously we don't want core to depend on ScalaCheck. Is there some way we can put the laws in core while supporting using the ScalaCheck labels to get useful output?

from cats.

fthomas avatar fthomas commented on July 22, 2024

I wouldn't call it a solution, but we could let the laws return two things that should be equal instead of a Boolean:

  def invariantIdentity[A](fa: F[A]): (F[A], F[A]) =
    (F.imap(fa)(identity[A])(identity[A]), fa)

ScalaCheck could then take care of comparing those two values.

from cats.

non avatar non commented on July 22, 2024

Right, or even just return the (A, A, (A, A) => Boolean) that algebra would be passing to Ops.run if you see what I mean.

from cats.

non avatar non commented on July 22, 2024

You could argue this makes all the laws less readable. I'm willing to create some kind of DSL here, ideally we can have laws that are clearly specified in a useful place, but which also produce useful messages when they fail.

from cats.

fthomas avatar fthomas commented on July 22, 2024

I think a small DSL could make the laws as readable as the Boolean-returning versions. Just with something like type Identity[A] = (A, A) and -> it reads a lot better.

  def invariantIdentity[A](fa: F[A]): Identity[F[A]] =
    F.imap(fa)(identity[A])(identity[A]) -> fa

from cats.

ceedubs avatar ceedubs commented on July 22, 2024

If Identity[A] is defined as anything other than Identity[A] = A I think it's going to really confuse people. Other than that a mini DSL sounds fine to me :)

from cats.

non avatar non commented on July 22, 2024

I think the benefit of a DSL would be to enable other kinds of laws besides those based on identical pairs, so I think we'd want something slightly different here.

(OTOH if we really only need to test that LHS is equal to RHS, pairs are fine.)

from cats.

fthomas avatar fthomas commented on July 22, 2024

I've now moved all current laws next to the type classes in my WIP branch (https://github.com/fthomas/cats/compare/wip/move-laws). The laws are now inner traits of the type classes which avoids the evidence parameters and the F. prefixes. What do you think?

from cats.

fthomas avatar fthomas commented on July 22, 2024

I should add that the definitions of the laws in my WIP branch are similiar to how they are defined in scalaz.

from cats.

julien-truffaut avatar julien-truffaut commented on July 22, 2024

@fthomas not sure to understand what's the benefit of having the law as inner trait?

from cats.

mpilquist avatar mpilquist commented on July 22, 2024

While I agree that defining the laws in the same source file as the type class has a lot of benefits, it still feels like it's test code that's included in non-test artifacts.

Also, with unidoc, each type class can link directly to a laws trait defined in the laws JAR, providing similar benefits to the suggested solution, without bloating the core JAR.

Ultimately, I wonder if we can separate the laws from their binding to Discipline like in the suggestion above, but still include them in the laws JAR.

from cats.

fthomas avatar fthomas commented on July 22, 2024

@julien-truffaut as top-level class:

trait Invariant[F[_]] {
  def imap[A, B](fa: F[A])(f: A => B)(fi: B => A): F[B]
}

class InvariantLaws[F[_]](implicit F: Invariant[F]) {
  def invariantIdentity[A](fa: F[A]): (F[A], F[A]) =
    F.imap(fa)(identity[A])(identity[A]) -> fa
}

as inner trait:

trait Invariant[F[_]] {
  def imap[A, B](fa: F[A])(f: A => B)(fi: B => A): F[B]

  trait InvariantLaws {
    def invariantIdentity[A](fa: F[A]): (F[A], F[A]) =
      imap(fa)(identity[A])(identity[A]) -> fa
  }
}

The inner trait does not require the context bound implicit F: Invariant[F] and instead of F.imap you can just write imap.

from cats.

fthomas avatar fthomas commented on July 22, 2024

@mpilquist In retrospect my main concern was the tight coupling between the laws and discipline code. If there are proper ScalaDoc links from the type classes to the law traits, I think that is also ok for me.

from cats.

julien-truffaut avatar julien-truffaut commented on July 22, 2024

I would also prefer the laws to be defined outside the TC trait. I agree with @fthomas a scaladoc link to reference the laws is a good documentation.

from cats.

fthomas avatar fthomas commented on July 22, 2024

Here is another proposal: https://github.com/fthomas/cats/compare/wip/move-laws2

  • each typeclass has now its dedicated Laws class in the cats.laws package
  • the discipline test code is moved into the cats.laws.discipline package

What do you think? Is this good enough to open a PR with these changes?

from cats.

mpilquist avatar mpilquist commented on July 22, 2024

Looks good to me

On Feb 8, 2015, at 8:03 AM, "Frank S. Thomas" [email protected] wrote:

Here is another proposal: https://github.com/fthomas/cats/compare/wip/move-laws2

each typeclass has now its dedicated Laws class in the cats.laws package
the discipline test code is moved into the cats.laws.discipline package
What do you think? Is this good enough to open a PR with these changes?


Reply to this email directly or view it on GitHub.

from cats.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.