These are chat archives for typelevel/scala

9th
Nov 2016
jeremyrsmith
@jeremyrsmith
Nov 09 2016 16:37

Is there an SI for partially applying type arguments? It seems with the changes made for partial unification of higher kinded types, it could be possible to allow something like

def foo[A, B, C](b: B, c: C): A = ???
foo[Int]("string", false) // A is fixed to Int; B and C are inferred as String and Boolean

given that the decision of SI-2712 is for type parameters to always be curried and applied left-to-right. It would have to be extended from kinds to application (which maybe introduces other problems?)

Miles Sabin
@milessabin
Nov 09 2016 17:03
I'd want to address that via multiple type parameter blocks.
So def foo[A][B, C](b: B, c: C): A = ???
Greg Pfeil
@sellout
Nov 09 2016 17:06
@jeremyrsmith Do you know the “kinda-curried type parameter” approach? That gives us a way to fake the multiple type parameter blocks somewhat.
jeremyrsmith
@jeremyrsmith
Nov 09 2016 17:07
@sellout the closest I'm aware of is the Aux pattern, but that doesn't extend to application
Greg Pfeil
@sellout
Nov 09 2016 17:08
That was weird … my Gitter client just decided to interleave both typelevel/general and typelevel/scala messages in here.
@jeremyrsmith Yeah, it’s a version of that pattern – it does work with application: https://github.com/quasar-analytics/quasar/wiki/Scala%5BQuasar%5D#partially-applied-type-parameters
That references @tpolecat’s original writeup, but we prefer a different syntax, so I linked to ours ;)
jeremyrsmith
@jeremyrsmith
Nov 09 2016 17:10
multiple type parameter blocks would be awesome though - things like Aux could largely go away, and a lot of shapeless proofs would clean up dramatically
@sellout ah, so you mean "builder" objects... I've used that, but it is a PITA in a lot of cases
Miles Sabin
@milessabin
Nov 09 2016 17:11
It's multiple implicit parameter blocks which make Aux go away.
The Aux you find in shapeless that is.
jeremyrsmith
@jeremyrsmith
Nov 09 2016 17:12
@milessabin it seems like that goes hand-in-hand with multiple type parameter lists... neither would be as useful without the other
Miles Sabin
@milessabin
Nov 09 2016 17:12
I've also used Aux for things similar to what @sellout linked to, but I think it's not such a good name in that case.
Greg Pfeil
@sellout
Nov 09 2016 17:13
@milessabin I am happy to name it something else – but at least the name never has to be referenced outside of that object.
Miles Sabin
@milessabin
Nov 09 2016 17:14
Indeed. The generalization of the multiple implicit parameter blocks PR that I posted a while back is to allow explicit, implicit value and type parameter blocks to be arbitrarily interspersed.
jeremyrsmith
@jeremyrsmith
Nov 09 2016 17:14
I was referring to shapeless Aux, yes - the pattern of dropping a type parameter into a type member (so it can be inferred) and then capturing it back in a structural type alias
Greg Pfeil
@sellout
Nov 09 2016 17:14
Woah, wait … interspersing type parameter blocks?
Miles Sabin
@milessabin
Nov 09 2016 17:14
@sellout there's a Cats ticket about this somewhere ... I think we converged on PartiallyApplied or something like that?
Sure, why not.
Greg Pfeil
@sellout
Nov 09 2016 17:15
@milessabin Heh, yeah, I called it PAT (partially-applied type) until someone at SD decided to repurpose Aux. So I’m on the same page. And alignment with Cats is definitely a valid justification for us. So, 👍🏾
Miles Sabin
@milessabin
Nov 09 2016 17:15
Everything gets erased.
Let me find the ticket.
Greg Pfeil
@sellout
Nov 09 2016 17:16
Yeah, I mean, I know this stuff is possible just excited to see that it could actually happen.
Would any of this get us to a point where we could basically have a natural transformation without trait FunctionK? I don’t quite see it, but there’s a lot I don’t see.
Miles Sabin
@milessabin
Nov 09 2016 17:18
@sellout here: typelevel/cats#577
@sellout I think we can get natural transformations out of a generalization of SAM conversions.
Paolo G. Giarrusso
@Blaisorblade
Nov 09 2016 17:19
@sellout Martin wrote somewhere that some change in Dotty made polymorphic values (what you want for natural transformations) feasible (though it'd require a SIP)
In theory this commit paves the way to allow polymorphic types as value types. A test of some of the basic functionality is in pending/pos/polyTypes. This does not work yet, because adapt forces every polytype it sees to be fully applied. Enabling this functionality should be a SIP and separate PR.
Greg Pfeil
@sellout
Nov 09 2016 17:20
@milessabin what’s a SAM conversion?
Miles Sabin
@milessabin
Nov 09 2016 17:21
Conversion of a function literal to a value of a type with a Single Abstract Method.
Paolo G. Giarrusso
@Blaisorblade
Nov 09 2016 17:22
Ah, so you want to do a SAM Conversion to F ~> G
Miles Sabin
@milessabin
Nov 09 2016 17:22
Currently only monomorphic methods are supported, but that could be generalized to polymorphic and dependent methods.
Yup.
Paolo G. Giarrusso
@Blaisorblade
Nov 09 2016 17:24
While Martin's comment is about supporting (in a farther future) ∀ A. F[A] => G[A] directly
jeremyrsmith
@jeremyrsmith
Nov 09 2016 17:25
does Java 8 support polymorphism in SAM interfaces?
Miles Sabin
@milessabin
Nov 09 2016 17:26
It was certainly planned. I'm not sure what ended up in the implementation.
jeremyrsmith
@jeremyrsmith
Nov 09 2016 17:26
or would there be some trick involved (like generating a monomorphic SAM at the call site when types are fixed)
Miles Sabin
@milessabin
Nov 09 2016 17:28
SAM conversions implement abstract types. The target type at the call site in this case would be polymorphic, ie. def apply[T](f: F[T]): G[T].
We'd need syntax for polymorphic and dependent function literals.
Greg Pfeil
@sellout
Nov 09 2016 17:29
@milessabin So, other than the Aux/PartiallyApplied bit – what do you think of the object containing the class (like in our wiki), vs the def+class (like in Cats)?
Miles Sabin
@milessabin
Nov 09 2016 17:32
What's the difference? You have the same def+class wrapped in an object ... is there something else I'm missing?
Greg Pfeil
@sellout
Nov 09 2016 17:37
@milessabin No – I just like that ours encapsulates them, and I was wondering if there was anything about scalac that might make it less desirable. One difference is how it appears in scaladoc – I think the non-object version is maybe slightly more obviously “callable”. ¯\_(ツ)_/¯
Miles Sabin
@milessabin
Nov 09 2016 17:39
Yes, I think that's nice.
I dislike all the private[this] in the cats PR.
Guillaume Martres
@smarter
Nov 09 2016 17:46
@jeremyrsmith In dotty you can do partial type application using named types: foo[A=Int]("string", false)
I think that's more flexible than the multiple type parameter blocks proposal
Miles Sabin
@milessabin
Nov 09 2016 17:48
Multiple interspersed type parameter blocks.
Guillaume Martres
@smarter
Nov 09 2016 17:48
What does that give you?
Miles Sabin
@milessabin
Nov 09 2016 17:49
So, eg. def foo[T](implicit ft: F[T])[U <: ft.T](u: U) ... etc.
Guillaume Martres
@smarter
Nov 09 2016 17:49
ah, so dependent types :)
Greg Pfeil
@sellout
Nov 09 2016 17:49
Yeah, I could use the hell out of that.
Miles Sabin
@milessabin
Nov 09 2016 17:50
@smarter I also really dislike the nominal aspect of that dotty syntax.
Guillaume Martres
@smarter
Nov 09 2016 17:50
Do you dislike that the type parameter name becomes part of the API?
Miles Sabin
@milessabin
Nov 09 2016 17:51
I dislike that it's impossible to abstract over.
Guillaume Martres
@smarter
Nov 09 2016 17:51
Can your proposal be abstracted over?
Miles Sabin
@milessabin
Nov 09 2016 17:51
It makes foo[A] fundamentally different from foo[B].
jeremyrsmith
@jeremyrsmith
Nov 09 2016 17:51
I'm not a big fan of named type arguments... especially since type parameter names are encouraged to be meaningless
or at least largely meaningless
Miles Sabin
@milessabin
Nov 09 2016 17:51
With corresponding method types, yes.
Which I think we can model with nested PolyTypes in scalac.
Guillaume Martres
@smarter
Nov 09 2016 17:53
If we had some kind of polymorphic value foo: [X,Y] => Bla then with the named type syntax you could maybe write foo[X=Int] too
Miles Sabin
@milessabin
Nov 09 2016 17:54
I think that it was a daft idea as a model for higher kinded types, and I think it's still a daft idea here.
Guillaume Martres
@smarter
Nov 09 2016 17:54
strong words!
Miles Sabin
@milessabin
Nov 09 2016 17:55
I speak as I find.
Guillaume Martres
@smarter
Nov 09 2016 17:55
well, I think your syntax is interesting too, but definitely more complicated
Miles Sabin
@milessabin
Nov 09 2016 17:55
It's a natural generalization of what we already have.
Guillaume Martres
@smarter
Nov 09 2016 17:56
named types have a nice parallel with named arguments, but maybe you dislike those too?
Miles Sabin
@milessabin
Nov 09 2016 17:56
I do :-)
Guillaume Martres
@smarter
Nov 09 2016 17:56
I understand your viewpoint better then, but I think it may not be shared by many Scala developers
also I have to go now, cheers
Paolo G. Giarrusso
@Blaisorblade
Nov 09 2016 20:06
@milessabin FWIW, named function arguments exist in Agda too (though for implicits only); while that makes meaningless parameter names part of the API, the current syntax makes the meaningless parameter order part of the API.
Miles Sabin
@milessabin
Nov 09 2016 20:07
The order is entirely meaningless.
Paolo G. Giarrusso
@Blaisorblade
Nov 09 2016 20:08
Yep, but you need to know it to pass arguments explicitly
Miles Sabin
@milessabin
Nov 09 2016 20:09
Oops s/is/isn't/ :-D
Paolo G. Giarrusso
@Blaisorblade
Nov 09 2016 20:10
So for traverse which type argument comes first, the Traversable or the Applicative?
In comparison, visible type application in Haskell runs into a similar problem. In both cases, making something insignificant (the order or the names) into part of the API is a slightly annoying transition.
Miles Sabin
@milessabin
Nov 09 2016 20:12
In some cases it's irrelevant, in others it matters. Consider any dependent method, for instance.
That's way I said: isn't entirely meaningless.
Paolo G. Giarrusso
@Blaisorblade
Nov 09 2016 20:19
Agreed on dependent methods.