I've not been able to come up with how to encode Obj
in Scala:
{-# LANGUAGE ExistentialQuantification #-}
data Obj = forall a. (Show a) => Obj a
instance Show Obj where show (Obj a) = "Obj " ++ show a
main = print $ show [Obj "hello", Obj 3, Obj True]
when run, the above produces the following output:
[Obj "hello",Obj 3,Obj True]
In Scala, however, this does not seem to compile:
forSome { type T; implicit val ev: Show[T] }
and neither does this:
forSome { type T : Show[T] }
Is this even possible at the type system level, or do I need to "capture" the type class instance using something like this:
class Obj[T](val x: T)(implicit val: Show[T]) // ...or similar
Any insight would be appreciated!
You got it almost right:
P.S I'd like to use
T
andshow
inapply
; notU
and_show
. If someone knows how to avoid shadowing, I'll appreciate!Alternatively you could use
forSome
:Here we have to use
Tuple2
(or other auxillary type) to captureShow
. I like the previous variant more. For me it's easier to wrap a mind around a type member.Also in Scala "Don Giovanni"
forSome
syntax will be eliminated in favour ofval pair: ({ type λ[T] = Tuple2[T, Show[T]] })#λ[_] }
, which works already too. I hope there will be some syntax support for type lambdas as well. kind-projector doesn't help in this situation (repeated use ofT
). Maybe something like in Typelevelscalac
:val pair: ([T] => Tuple2[T, Show[T])[_])
.Another foundational change will be:
So the both forms will be equivalent from the point of view of the compiler (in former we unpack the tuple). I'm not 100% sure what are the differences currently, if there are any.
P.S. The Troubles with Types helped me understand scala's current type system quirks.
I've "packaged" Oleg's answer into this generic and (seemingly) reusable structure:
then,
data Obj = forall a. (Show a) => Obj a
can be implemented like this: