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

Add TypeOf utility #692

Merged
merged 7 commits into from
Mar 3, 2017
Merged

Add TypeOf utility #692

merged 7 commits into from
Mar 3, 2017

Conversation

Atry
Copy link
Contributor

@Atry Atry commented Mar 3, 2017

No description provided.

@milessabin
Copy link
Owner

Could you add a test where the expression performs a type-level computation via an implicit?

@Atry
Copy link
Contributor Author

Atry commented Mar 3, 2017

@milessabin The last one is via implicit:

val tu2: Either[String, TypeOf.`the.apply: Bar[String]`.U] = Right(23)

Note the the.apply

@milessabin
Copy link
Owner

milessabin commented Mar 3, 2017

Ahh, right. I really meant something a little more sophisticated than that, which justifies using this construct rather than expanding the type by hand. A non-trivial type-level computation would be good here (maybe a Sum of Nat's), and maybe a use of (Labelled)Generic[Foo].Repr.

the.apply is fairly odd usage TBH ... I wouldn't expect to see it in real code.

@codecov-io
Copy link

codecov-io commented Mar 3, 2017

Codecov Report

Merging #692 into master will increase coverage by 0.04%.
The diff coverage is 100%.

@@            Coverage Diff             @@
##           master     #692      +/-   ##
==========================================
+ Coverage   83.39%   83.44%   +0.04%     
==========================================
  Files          65       65              
  Lines        2590     2591       +1     
  Branches       91       91              
==========================================
+ Hits         2160     2162       +2     
+ Misses        430      429       -1
Impacted Files Coverage Δ
core/src/main/scala/shapeless/typeoperators.scala 100% <100%> (ø)
core/src/main/scala/shapeless/syntax/hlists.scala 90.47% <0%> (+0.79%)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 20013c4...ca45457. Read the comment docs.

@Atry
Copy link
Contributor Author

Atry commented Mar 3, 2017

@milessabin I added a zipWithIndex test on HList

@Atry
Copy link
Contributor Author

Atry commented Mar 3, 2017

One more thing, I think it would be possible to create a compiler plugin, which supports a special @forExample annotation:

type A = T@forExample(expr)

which converts to

type A = TypeOf.`expr:T`.type

@Atry
Copy link
Contributor Author

Atry commented Mar 3, 2017

For example:

type T = Any@forExample(Generic[(Int, String, Boolean)].to((1, "foo", true)).zipWithIndex)

As a result, T is (Int, _0) :: (String, _1) :: (Boolean, _2]) :: HNil

@milessabin
Copy link
Owner

Interesting. I think you're getting into refined and singleton-ops territory here.

@milessabin
Copy link
Owner

A test using Generic?

@Atry
Copy link
Contributor Author

Atry commented Mar 3, 2017

@milessabin I hope it can perform type-level ops like singleton-ops. However, it is evaluated before method applying, preventing it get the actually type of a value.

@milessabin
Copy link
Owner

Does this work?

case class Baz(i: Int, s: String)
implicit val genBaz: TypeOf.`Generic[Baz]` = cachedImplicit
val reprBaz = genBaz.to(Bar(23, "foo"))
typed[Int :: String :: HNil](reprBaz)

If it does, could you add it as a test. If it doesn't it'd be good if we could make it work.

@milessabin
Copy link
Owner

Or should that be,

implicit val genBaz: TypeOf.`Generic[Baz]`.type = cachedImplicit

@milessabin
Copy link
Owner

Anyhow, the point is that this would capture the Repr type in the type ascription which is quite awkward to do otherwise. See here.

@milessabin
Copy link
Owner

Or, rather, here.

@Atry
Copy link
Contributor Author

Atry commented Mar 3, 2017

Of course, TypeOf can infer Repr from implicits. ca45457#diff-9e42d9f002bf1026dba49cfe00ca4ebbR175

@milessabin
Copy link
Owner

Great stuff. It's not immediately obvious that that would work, because the interactions with cachedImplicit and the semantics around implicit definitions with and without type ascriptions are quite subtle. I could easily believe that the val might be initialized to null in that case.

It's great that this works ... it's a really useful addition to the toolbox ... thanks! :-)

@milessabin milessabin merged commit 0904b78 into milessabin:master Mar 3, 2017
@Atry
Copy link
Contributor Author

Atry commented Mar 4, 2017

I guess the would work as well:

implicit val genBaz: the.`Generic[Baz]`.type = cachedImplicit

@milessabin
Copy link
Owner

Oh! Interesting ... that hadn't occurred to me ... does it work?

@Atry
Copy link
Contributor Author

Atry commented Mar 4, 2017

Works for me

@milessabin milessabin added this to the shapeless-2.3.3 milestone Dec 30, 2017
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

Successfully merging this pull request may close these issues.

None yet

3 participants