-
We disagree over code formatting of plurals. I think we should only code format types and values that the reader could lookup. E.g.,
Hlist
s vs.HLists
. Ditto for function names (flatMapping
isn't a method I could find). I could drone on about this, but I'll spare you. -
For links, we should settle on a house style: do we hyperlink the number in "Chapter 5" or the whole phrase. Looks like you have consistently used the number. So ignore this for now.
BTW, I've worked from the PDF. I have pasted text from the PDF: that sometimes goes wonky, but tried to fix this gist when I spot it.
We assume shapeless 2.3.2 and either Typelevel Scala 2.11.8+ or Light- bend Scala 2.11.9+ / 2.12.1+
- Enough to say shapeless 2.3.2? Reason: versions of Scala you can use are the versions it is published against, and presumably 2.12.0 and 2.12.1 are right around the corner.
- Also: seems very detaily in the second sentence. Could be moved into the Source code for examples box on page 10.
You could then run the first sentence right into the next para.
Perhaps we need a box on why shapeless is lower-case s (i.e., ask Miles).
Suggestion: As a rule shapeless is written just like that: with a lower-case s. This looks plain weird when starting a sentence, so use a capital s in that case.
First para, drop first sentence: "As Scala developers...".
Boilerplate and repetition are the same thing. Remove "and boilerplate".
## Page 8
Now that both sets of data are the same type, we can serialize them with the same function:
Is it clear to a reader new to shapeless that these are the same type?
Consider:
Both values are now the same type.
They are both heterogeneous lists (HLists
for short) of String
, Int
, Boolean
.
We will look at HLists
and the important role they play soon.
However, for what is important now is that because the values have the same type, we can serialize them with the same function:
First bullet point:
we introduce generic representations and shapeless'
Generic
type class
Is that two concepts, or is it better expressed as: we introduce generic representations as powered by shapeless' Generic
type class
We use CSV encoding as an example
If I expand out CSV I get: "we use command separated value[s] encoding as an example" which doesn't scan. It's fine if you read it as "sea ess vee".
Alternative would be: We use an encoding of CSV as an example. Meh.
In Chapter 4 we cover some more theory:
Seem weak. How about...
In Chapter 4 we introduce the theory and programming patterns we need to generalise the techniques from earlier chapters. Specifically we look at dependent types, dependently typed functions, and type level programming. This allows us to access more advanced applications of shapeless.
We also introduce some new theory
Drop "some". If you want word, perhaps "additional theory".
with TODOs to fill in,
s/b "with TODOs for you to fill in"
There’s some macro magic going on behind the scenes
Consider removing the "magic" for the reader: Shapeless provides a macro that allows us to obtain instances of Generic
with one short line of code:
Every coproduct type is terminated with CNil, which is an empty type with no values, similar to Nothing. We can never instan ate CNil or build a Co- product purely from instances of Inr. We always have exactly one Inl in a value.
This para is confusing me over the type and the value. I think a fix is to para break after Nothing
:
Every coproduct type is terminated with CNil, which is an empty type with no values, similar to Nothing.
We can never instan ate CNil or build a Co- product VALUE purely from instances of Inr. We always have exactly one Inl in a value.
--
Traditionally the only limitation to this has been ADTs. The compiler can't pull apart the types of case classes and sealed traits, so we have always had to define instances for ADTs by hand. Shapeless' generic representations change all of this, allowing us to derive instances for any ADT for free.
This sentence doesn't work for me. How about...
Even with this power, the compiler can't automatically pull apart our case classes and sealed traits. We are required to define instances for our ADTs by hand. Shapeless's generic...
We’ll use two rules: one for an HNil and one for :::
The ::
and :
make this confusing to read. How about...
_We'll use two rules: one for ::
and one for HNil
:
Not ideal as the implementation order is HNil and then ::.
Alternative:
We’ll use two rules: one for an HNil and one for :: as shown below:
We won’t dwell on the details here, but the trick to solving this kind of problem...
We don't go into any details of the problem. Consider dropping the first part of the sentence to leave:
The trick to solving...
The generic representation for
Shape
isRectangle :+: Circle :+: CNil
. We can write genericCsvEncoders
for:+:
andCNil
using the same principles we used forHLists
. Our existing product encoders will take care ofRectangle
andCircle
:
The "Our exiting product encoders" sentence at the end here feels like it's a distraction in the flow.
How about:
The generic representation for Shape
is Rectangle :+: Circle :+: CNil
.
In Section 3.2 we defined the product encoders forRectangle
and Circle
.
Now to write the generic CsvEncoders
for :+:
and CNil
we can use the same principles we used for HLists
:
Should that title be divergence with a lower case d? Not sure.
However, we can’t use it on compound expressions: the compiler has to be able to determine the literal value straight from the source:
Two minor things:
- two colons in the sentence
- I have no idea what "straight for the source" means.
Suggest replacing with this alone:
However, we can’t use it on compound expressions:
There's a flag to enable this stuff, right? Worth saying that?
As of Lightbend Scala....., with the -wibble flag enabled, we now have direct syntax support...
This number is an Int in two worlds: at runtime, where it has methods like + and *, and at compile- me, where the compiler uses the type to calculate which pieces of code work together and to search for implicits
I don't think of the methods + and * as being in the runtime world.
at runtme, where the work of methods such as + and * happen; and at compile time... maybe?
## Page 58
I feel there needs some kind of motivation or intuition for the use of the word Witness. One to hassle Miles about.
Two items here:
-
first, it feels like an abbrupt transition from FiledType stuff into Records and labeleed generic. If that was building block material for the next section, maybe we can say that. If it's complementary, maybe we can say that. Just feels like it needs a sentence here to smooth the transition and ... more narrative.
-
second, there's a box:
TODO: Insert link to records chapter if we have one
- I guess just cut this. Was going to do it, but didn't want to if it has meaning for you.
In the next chapters we will look at two suites of that require further the- ore cal discussion.
Something has got messed up there. "In the next chapters we will look at " is fine, then it falls apart and I can't figure out what you want to say. Sorry!
Ah, "two suites of ops", maybe?
eliding a lot of extra stuff that makes real shapeless Polys much more flexible
Nothing wrong with this, and is quite casual. Alternative would be:
eliding much that makes real shapeless Polys much more flexible
Poly1 through Poly2
Should that be to Poly22 ? I don't know... I couldn't figure it out in the 10 seconds I spent searching.
## Page 97
You say...
We will show how Length and Nat form a crucial part of the implementaion:
The code block following the : is just the Random trait.
I think you want to say:
_ We will show how Length and Nat form a crucial part of the implementaion. As usual, we start with the definition of our typeclass: _
(However, the start of the next section is "Let's start with some basic instances". So if you go for the above, maybe that should become "We continue with some basic...")
and ensures we will never call cnilProduct.get
I don't get how the change guarantees that. Don't worry about it.... I'm reading at speed, and this is more a note for me to come back and study that. (Because there's no Length instance for a CNil or something maybe).
Feels like you need a wrapping-up sentence here.
Using generic programming we have been able to genererate random instances for arbitrary products and coproducts.
Bleh. Maybe not.
Wikkid. Thanks! I've incorporated almost everything:
flatMapping
is taking things a bit far. I've de-monospaced that bit :)