These are chat archives for typelevel/scala

11th
Dec 2016
Greg Pfeil
@sellout
Dec 11 2016 02:46
So, is it unsurprising behavior (if it is, I think I understand it) that calling def foo[T, F[_]: Functor](…)(implicit T: Recursive.Aux[T, F]) sometimes results in ambiguous implicits for Functor[F], but calling def foo[T, F[_]](…)(implicit T: Recursive.Aux[T, F], F: Functor[F]) doesn’t? (BTW, this is one of those places that I think multiple implicit lists would fix things, as F[_] would disappear, since we could pull it out as T.Base in later parameter lists.)
Rob Norris
@tpolecat
Dec 11 2016 02:51
Does it fail in the same way if you reverse the order of the implicit args?
I always forget where context bounds end up.
Greg Pfeil
@sellout
Dec 11 2016 02:59
@tpolecat I assume it does. Context bounds end up at the start. But I can try it, I suppose …
@milessabin Can one take advantage of multiple implicit lists and still be depended on by LBS-using projects?
Greg Pfeil
@sellout
Dec 11 2016 03:10
@tpolecat Yes, it fails in the same way. I’m like “ok, it’s just resolving stuff left-to-right, so this makes sense …” but I keep thinking there should be more unification in resolving the types. Maybe there is, though – as really, in Scala, this isn’t about type inference. The only way we narrow down F is by resolving the Recursive implicit. It isn’t like Haskell where Base is defined as an open type family and is inferred without relying on the type class.
I should really just stop using constraints anyway. I use them because 1. they’re shorter and 2. they don’t require me naming things. But they also mean implicits are often in weird orders and I rely on implicit ops conversions.
Miles Sabin
@milessabin
Dec 11 2016 09:16
@sellout the variant I experimented with is binary compatible.
The semantics were unchanged though ... context bounds are still rewritten to being at the head of the first implicit parameter list.
And it sounds like you're having a "left to right" problem, so on its own multiple implicit parameter blocks wouldn't fix it.
Pascal Voitot
@mandubian
Dec 11 2016 10:41
yep I agree it looks a "left to right" issue... you need F first to search the Functor[F]... we can't ask scalac to guess too many things ;)
Greg Pfeil
@sellout
Dec 11 2016 14:39
@milessabin The reason multiple implicits would fix this for me (I think) is that it would eliminate F[_] as a type param. I’d have def foo[T](…)(implicit T: Recursive[T])(implicit B: Functor[T.Base]) So, yes, I’d have to still put the Functor last, but that is forced by being able to access the members of T.
Miles Sabin
@milessabin
Dec 11 2016 17:46
You can write that in vanilla LBS with the aux pattern.
Greg Pfeil
@sellout
Dec 11 2016 18:17
@milessabin Isn’t that what my previous example is doing?
But I need the F[_] type parameter in that case, don’t I?
And using the Aux pattern also pushes me toward using the PartiallyApplied pattern, so I can do [T][F[_]], but that then forces me to specify T even when it can be inferred. And multiple implicit lists just cleans all of that up. No need for PartiallyApplied, no need for Aux (especially since Aux is causing problems with type class hierarchies), and no need for F[_].
Miles Sabin
@milessabin
Dec 11 2016 18:23
Sorry, I've lost track of what you're attempting here. Can you post a gist of the code the way you'd like to be able to write it?
Miles Sabin
@milessabin
Dec 11 2016 18:41
Gotcha.