Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hitting apply limit when using functor application #504

Closed
mdedetrich opened this issue Sep 1, 2013 · 6 comments
Closed

Hitting apply limit when using functor application #504

mdedetrich opened this issue Sep 1, 2013 · 6 comments
Milestone

Comments

@mdedetrich
Copy link

We have pieces of code where we are hitting the hardcoded limit for functor application

As a simple test case, the following piece of Scala code fails

  val test = (
    "1".successNel[String] |@|
    "2".successNel[String] |@|
    "3".successNel[String] |@|
    "4".successNel[String] |@|
    "5".successNel[String] |@|
    "6".successNel[String] |@|
    "8".successNel[String] |@|
    "9".successNel[String] |@|
    "10".successNel[String] |@|
    "11".successNel[String] |@|
    "12".successNel[String] |@|
    "13".successNel[String] |@|
    "14".successNel[String]
  )

where as this works fine

  val test = (
    "1".successNel[String] |@|
    "2".successNel[String] |@|
    "3".successNel[String] |@|
    "4".successNel[String] |@|
    "5".successNel[String] |@|
    "6".successNel[String] |@|
    "8".successNel[String] |@|
    "9".successNel[String] |@|
    "10".successNel[String] |@|
    "11".successNel[String] |@|
    "12".successNel[String] |@|
    "13".successNel[String]
  )

Is there any work around for this hard limit, or plans to address this limitation (it seems to be the similar issue that scala has with things like tuples and whatnot)?

@larsrh
Copy link
Contributor

larsrh commented Sep 1, 2013

Yes, this is a known limitation. The syntax you're using is provided by ApplicativeBuilder, which only goes up to 14, and since each arity requires more boilerplate, this restriction is not going to be lifted. There are better ways to express this though, depending on your use case.

It seems that all your elements have the same type – ValidationNel[String, String]. Depending on what you want to do with them, you could use:

scala> List("1".successNel[String], ...).sequenceU
res0: scalaz.Validation[scalaz.NonEmptyList[String],List[String]] = Success(List(1, 2, ...))

However, if your actual code requires the elements to be of different type, you can use shapeless-contrib:

sequence(
  "1".successNel[String] ::
  "2".successNel[String] ::
  ... ::
  HNil
).map { case x :: y :: ... :: HNil =>
  f(x, y, ...)
}

This exactly mimics the previous ApplicativeBuilder syntax. Basically: replace |@| by ::, wrap it into sequence, and map instead of apply to apply a function.

Does either solution work for you?

@mdedetrich
Copy link
Author

The example I used just demonstrated the problem, the real code has many different types that are wrapped in Validation

The second solution looks like it can work fine, as long as I get a nel of failures. I am wondering, if the issue with ApplicativeBuilder should be better solved by making it a macro (if it goes down to boilerplate), since that way you can just specify the max arity without being limited by a hard coded limit?

@larsrh
Copy link
Contributor

larsrh commented Sep 1, 2013

The second solution looks like it can work fine, as long as I get a nel of failures.

Yes.

I am wondering, if the issue with ApplicativeBuilder should be better solved by making it a macro (if it goes down to boilerplate), since that way you can just specify the max arity without being limited by a hard coded limit?

There is no actual need for macros here, since HLists already solve the arity problem very neatly. I don't think you can get any better than this, given that in Scala, partially applied functions and currying are not as pervasive as in Haskell, where <$> and <*> don't suffer from these problems.

@mdedetrich
Copy link
Author

Im attempting to use the code you mentioned above, however it seems that the statement function doesn't exist in the shapeless-contrib package that you linked me to

@mdedetrich
Copy link
Author

Actually nvm, it seems to be in SNAPSHOT-2.0 which is no longer in maven repos

@larsrh
Copy link
Contributor

larsrh commented Sep 2, 2013

It's not "no longer" in Maven repositories; you can fetch it from the snapshot repository on Sonatype. There will be a proper released version (0.2) though, as soon as shapeless 2.0 is out.

@larsrh larsrh closed this as completed Sep 2, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants