Re: [scala-user] Time to encourage meaningful type parameter names? Discuss

534 views
Skip to first unread message

Josh Suereth

unread,
Nov 17, 2011, 7:51:01 AM11/17/11
to scala...@googlegroups.com, scala-debate

Yet another thread that probably belongs on scala-debate.

AND to answer with my opinion :  I think using meaningful type parameter names can make sense, but there's a balance to be had.

On Nov 16, 2011 1:53 PM, "Ken McDonald" <ykke...@gmail.com> wrote:
This comes from thinking about the alleged complexity of Scala (others' arguments have convinced me it is a real problem in the corporate world), my own experiences as I start to penetrate a little bit of the "inner core" of Scala, and most of all, trying to be productive and ask, "Are there simple ways to mitigate the complexity problem?" (Assuming you believe it is a problem.)

First, consider the following method:

def someMeaningfulName(x: Int, y: String, z: Long) {...}

I don't know about you, but I have never worked in an environment where this would be considered acceptable code (unless x, y, and z actually had special meaning in the problem space). I think it's a given that good software engineering demands meaningful variable names, both internal and visible.

Now consider the following type signature:

flatMap [BThat] (f: (A) ⇒ GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That

There are three type parameters, A, B, and That. None are meaningful. Due to the fortunate inclusion of f: in the type, it's fairly easy to figure out the meanings of A and B. We can finally figure out the meaning of That when we reach the end of the line, at which point we need to reread the entire line to put everything together. (OK, you may not. I do, and I submit that most programmers will need to do so once or more.)

In fairness, there was a valid reason for using one-char type param back when type params were new; the declarations were simply (usually container classes), and the one-char rule made it obvious what was a type param and what was an actual type. Note the above def'n has already violated the one-char rule, without really adding value.

How about this

flatMap [resultElementType, resultType] (f: (inputElementType) ⇒ GenTraversableOnce[resultElementType])(implicit bf: CanBuildFrom[List[inputElementType], resultElementType, resultType]): resultType

This is much more verbose, but to someone unaccustomed to Scala collections, it is also much clearer. I've taken the liberty of using initial lowercase to denote a parameter rather than an actual type; I believe this is illegal, but I simply wanted to show how things could be made more readable.

If you're an experienced Scala user, this may not seem a big deal, just extra characters. Consider the process of reading the type signature from left to right, understanding as we go:

     flatMap [BThat] 

vs. 
     flatMap [resultElementType, resultType]

The second has immediate meaning. The first does not.

The example I chose was mid-level in complexity--it is as the top of what a Scala novice should encounter, but nowhere near as complex as one might encounter in Scala internals or scalaz.

I believe that encouraging meaninful type parameter names would help the perceived "Scala complexity" problem in two ways. First, it makes the more complex "beginner's" Scala signatures more immediately understandable to beginners. Second, it make intellectually sophisticated Scala code more acceptable to the mainstream by making it more readable.

OK, that's it. Discuss :-)


Thanks,
Ken

Tony Morris

unread,
Nov 17, 2011, 8:13:54 AM11/17/11
to Matthew Pocock, scala-...@googlegroups.com
On 17/11/11 22:56, Matthew Pocock wrote:
> On 17 November 2011 12:11, Tony Morris <tonym...@gmail.com> wrote:
>
>> It is extremely important to pick meaningless names. The moment you
>> project meaning is the moment you start making all those mistakes that
>> we so often see.
>>
> Many times the types are not devoid of meaning. Consider:
>
> trait Graph[A, B]
>
> vs
>
> trait Graph[N, E]
>
> vs
>
> trait Graph[Node, Edge]
>
> vs
>
> trait Graph[TheNodeType, TheEdgeType]
>
> Option 3 of these is (imao) optimal, as it clearly describes what role the
> types play without using unnecessarily verbose names. If you're not
> 'projecting meaning' on these two type parameters, you're not understanding
> the API. I've no problem with List[A], as there's nothing much to tell
> users about A. In a library like scalaz, consistent use of single-letter
> type parameters goes a long way, but then you have things like what the
> default letter should be for Monad vs Monoid.
>
> I'll bug out here, as I agree this should go to -debate until/unless it
> results in an agreement to go through the core libs renaming things, in
> which case I'd be happy to give up a 'documentation saturday' to helping
> rename things.
>
> Matthew
>
>
>> --
>> Tony Morris
>> http://tmorris.net/
>>
>>
>>
>

This is exactly the mistake I refer to. Now define your operations on
the data type. What do those operations (the important bits) say about
nodes and edges? Exactly, nothing, nothing at all -- now you're stuck in
a cognitive quagmire. Please allow me to politely decline your invitation.

--
Tony Morris
http://tmorris.net/


Matthew Pocock

unread,
Nov 17, 2011, 8:58:11 AM11/17/11
to tmo...@tmorris.net, scala-...@googlegroups.com
[I'm now subscribed to scala-debate - sorry if you got this twice]

On 17 November 2011 13:13, Tony Morris <tonym...@gmail.com> wrote:
On 17/11/11 22:56, Matthew Pocock wrote:
> trait Graph[TheNodeType, TheEdgeType]

This is exactly the mistake I refer to. Now define your operations on
the data type. What do those operations (the important bits) say about
nodes and edges?

There is no meaningful isomorphism that I can repeatedly apply to Graph[Node, Edge] to get a Graph[Edge, Node] and then apply again to get back to the original graph. The nodes and edges play distinct roles. Naming them after these roles is useful documentation for the user.
 
Exactly, nothing, nothing at all

It tells me a great deal about the graph API. It doesn't tell me anything about the specific choices of concrete types for Node/Edge, but that is not what type parameter names are for. It tells me what role they play in the graph, which is what type parameter names are for.
 
-- now you're stuck in
a cognitive quagmire. Please allow me to politely decline your invitation.

No, now I have a documented type, using nomenclature that people are used to, where people don't have to constantly look in 2 or 3 places to figure out if A or B is the type that represents an edge or if it is the type that represents a node. Most people are not compilers and find it easier if definitions can be understood with the minimum of needing to correlate terms with other definitions.

Honestly, I'm not getting what 'cognitive quagmire' I can fall into by calling the type in my graph that is being used for nodes Node rather than naming it A. It's a graph of nodes linked by edges ffs! We should be calling the node type Node and the edge type Edge. Anything else is obfuscation.

Matthew


--
Tony Morris
http://tmorris.net/





-- 
Dr Matthew Pocock
Integrative Bioinformatics Group, School of Computing Science, Newcastle University
skype: matthew.pocock
tel: (0191) 2566550

√iktor Ҡlang

unread,
Nov 17, 2011, 9:03:41 AM11/17/11
to Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
On Thu, Nov 17, 2011 at 2:58 PM, Matthew Pocock <turingate...@gmail.com> wrote:
[I'm now subscribed to scala-debate - sorry if you got this twice]

On 17 November 2011 13:13, Tony Morris <tonym...@gmail.com> wrote:
On 17/11/11 22:56, Matthew Pocock wrote:
> trait Graph[TheNodeType, TheEdgeType]

"The" can be dropped since it cannot be anything else.
"Type" can be dropped since it can only be a type, you don't write: "val theThingVal = new Thing"
 
trait Graph[Node, Edge] <--- Looks great to me




--
Viktor Klang

Akka Tech Lead
Typesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang

Matthew Pocock

unread,
Nov 17, 2011, 9:47:43 AM11/17/11
to Philippe Lhoste, scala...@googlegroups.com, scala-...@googlegroups.com
Hi,

On 17 November 2011 14:34, Philippe Lhoste <Phi...@gmx.net> wrote:
On 17/11/2011 13:51, Josh Suereth wrote:
Yet another thread that probably belongs on scala-debate.

AND to answer with my opinion : I think using meaningful type parameter names can make
sense, but there's a balance to be had.

Yes.
When I discovered Scala, I was disconcerted, not to say "shocked", by these one-letter type names. Looked like those old C programs where developers valued conciseness over expressiveness. You know, lines like: if (lh->v.u.s.aux == v->u.s.info)

Same here. I'd previously done a lot of Java and a few years of Haskell. I found much of the haskell libs to be impenetrable due to single-letter (and often non-mnemonic) type names, even after quite a while working with them.
 

On the other hand, there can be some confusion between real types (classes, etc.) and abstract types (those used in collections, not knowing in advance what they would be); perhaps even potential clashes (?).

Agreed. I have type parameters rendered in italic and type alases as italic+bold in intellij idea. I'm not a fan of Christmas-tree highlighting, but this seems to help.
 
Matthew

--
Philippe Lhoste
--  (near) Paris -- France
--  http://Phi.Lho.free.fr
--  --  --  --  --  --  --  --  --  --  --  --  --  --

Daniel Sobral

unread,
Nov 17, 2011, 10:25:41 AM11/17/11
to √iktor Ҡlang, Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
2011/11/17 √iktor Ҡlang <viktor...@gmail.com>

>
>
> On Thu, Nov 17, 2011 at 2:58 PM, Matthew Pocock <turingate...@gmail.com> wrote:
>>
>> [I'm now subscribed to scala-debate - sorry if you got this twice]
>> On 17 November 2011 13:13, Tony Morris <tonym...@gmail.com> wrote:
>>>
>>> On 17/11/11 22:56, Matthew Pocock wrote:
>>> > trait Graph[TheNodeType, TheEdgeType]
>
> "The" can be dropped since it cannot be anything else.
> "Type" can be dropped since it can only be a type, you don't write: "val theThingVal = new Thing"
>
> trait Graph[Node, Edge] <--- Looks great to me

Except you just killed Node and Edge as trait/class names. At the very
least, I'd call them ANode and AnEdge.

--
Daniel C. Sobral

I travel to the future all the time.

√iktor Ҡlang

unread,
Nov 17, 2011, 10:29:03 AM11/17/11
to Daniel Sobral, Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com


2011/11/17 Daniel Sobral <dcso...@gmail.com>

trait Graph[N/*ode*/, E/*dge*/]
 

--
Daniel C. Sobral

I travel to the future all the time.

Simon Ochsenreither

unread,
Nov 17, 2011, 10:35:52 AM11/17/11
to scala-...@googlegroups.com, Daniel Sobral, Matthew Pocock, tmo...@tmorris.net
Afaik C# prefixes type parameters with T and return type parameters with R ... but they also use I as a prefix for interfaces. The last holdout of Hungarian notation?

Daniel Sobral

unread,
Nov 17, 2011, 11:42:04 AM11/17/11
to √iktor Ҡlang, Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
2011/11/17 √iktor Ҡlang <viktor...@gmail.com>:

>
>> > trait Graph[Node, Edge] <--- Looks great to me
>>
>> Except you just killed Node and Edge as trait/class names. At the very
>> least, I'd call them ANode and AnEdge.
>
> trait Graph[N/*ode*/, E/*dge*/]

Won't show up on Scaladoc, so what's the point? Nope, I still prefer
ANode and AnEdge. :-)

Daniel Sobral

unread,
Nov 17, 2011, 11:42:55 AM11/17/11
to scala-...@googlegroups.com, Matthew Pocock, tmo...@tmorris.net

You should see that Uncle Bob has to say about prefixing interfaces
with I. Pretty funny! :-)

Michael Schmitz

unread,
Nov 17, 2011, 1:11:44 PM11/17/11
to Daniel Sobral, √iktor Ҡlang, Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
We already have great entries in the scaladoc about type parameters.

http://www.scala-lang.org/api/current/index.html#scala.collection.Map

Peace. Michael


2011/11/17 Daniel Sobral <dcso...@gmail.com>:

Matthew Pocock

unread,
Nov 17, 2011, 1:21:15 PM11/17/11
to Michael Schmitz, Daniel Sobral, √iktor Ҡlang, tmo...@tmorris.net, scala-...@googlegroups.com
Yes.... Wouldn't Map[K, V] or Map[Key, Value] be more self-explanatory? Peace.

2011/11/17 Michael Schmitz <mic...@schmitztech.com>

Michael Schmitz

unread,
Nov 17, 2011, 1:24:36 PM11/17/11
to Matthew Pocock, Daniel Sobral, √iktor Ҡlang, tmo...@tmorris.net, scala-...@googlegroups.com
Well, fair point with Map[K, V]--I'm with you there!

Alex Repain

unread,
Nov 17, 2011, 1:34:42 PM11/17/11
to Matthew Pocock, Michael Schmitz, Daniel Sobral, √iktor Ҡlang, tmo...@tmorris.net, scala-...@googlegroups.com


2011/11/17 Matthew Pocock <turingate...@gmail.com>

Yes.... Wouldn't Map[K, V] or Map[Key, Value] be more self-explanatory? Peace.



There will always be people to not catch [K,V] as [Key, Value], and others to not catch what is Key or Value because they just don't know what a Map is (let's say the hereby example is easier than the general case). Using A,B,C and so on is a way to force the API user to know his tool, to understand it, and to RTFDocumentation - of course yes, you'd better document your code if it uses abstract {type names} or value names. As for using longer names, I'd say as stated before : if your concepts are abstract (pure mathematics, categories, formal systems in computer science) then use abstract names. Else, just make sure it's not conflict-prone ... Graph[N,E] seems just fine to me, Graph[A,B] is also fine. Graph[Node,Edge] takes risk in conflicting with already defined types (as a Graph API user, I would be tempted to code """type Node = Container[SomeType, AnotherOne, ...]""").

All the above IMHO.

Alex




--
Alex REPAIN
ENSEIRB-MATMECA - student
TECHNICOLOR R&D - intern
BORDEAUX I      - master's student

SCALA           - enthusiast


Rex Kerr

unread,
Nov 17, 2011, 1:45:56 PM11/17/11
to Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
On Thu, Nov 17, 2011 at 7:56 AM, Matthew Pocock <turingate...@gmail.com> wrote:
On 17 November 2011 12:11, Tony Morris <tonym...@gmail.com> wrote:
>
It is extremely important to pick meaningless names. The moment you
project meaning is the moment you start making all those mistakes that
we so often see.

Many times the types are not devoid of meaning. Consider:

trait Graph[A, B]

Bad.  Now I have to remember whether your graphs have nodes first or edges first.  I don't want to have to do that.
 
trait Graph[N, E]

Good!  Now I don't have to remember!
 
trait Graph[Node, Edge]

Why all the extra letters?  I already knew everything I needed to know.
 
trait Graph[TheNodeType, TheEdgeType]

This is just mean.

Actually, these are all bad.  Shouldn't it be

trait Graph[N <: Node, E <: Edge]

where Node and Edge are some traits that define the minimal possible interface required for something to be considered a node or an edge?  Maybe even

trait Graph[N <: Node, E <: Edge[N]]

depending on the edge interface?

Now we can see why Graph[Node, Edge] is the wrong choice.  You have labeled the types with _what you want_ without specifying that _they must be what you want_.  The more you insist with your names that you will in fact put the correct thing in that slot, the less likely you are to make the compiler insist on your behalf, and therefore the more burden you are taking upon yourself.

This is why I think the sweet spot is [N,E].  You want _some_ mnemonic because you want to know for yourself (as well as the compiler knowing) that nodes come before edges.  But [Node, Edge] is deceptive, and also steals the name Node and Edge away from what you probably really want (which are Node and Edge traits or classes).

  --Rex

Seth Tisue

unread,
Nov 17, 2011, 1:56:15 PM11/17/11
to scala-...@googlegroups.com
On Thu, Nov 17, 2011 at 1:45 PM, Rex Kerr <ich...@gmail.com> wrote:
> This is why I think the sweet spot is [N,E].  You want _some_ mnemonic
> because you want to know for yourself (as well as the compiler knowing) that
> nodes come before edges.  But [Node, Edge] is deceptive, and also steals the
> name Node and Edge away from what you probably really want (which are Node
> and Edge traits or classes).

+1

--
Seth Tisue | Northwestern University | http://tisue.net
lead developer, NetLogo: http://ccl.northwestern.edu/netlogo/

Erik Osheim

unread,
Nov 17, 2011, 2:01:00 PM11/17/11
to Rex Kerr, Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
On Thu, Nov 17, 2011 at 01:45:56PM -0500, Rex Kerr wrote:
> This is why I think the sweet spot is [N,E]. You want _some_ mnemonic
> because you want to know for yourself (as well as the compiler knowing)
> that nodes come before edges. But [Node, Edge] is deceptive, and also
> steals the name Node and Edge away from what you probably really want
> (which are Node and Edge traits or classes).

Agreed.

I find the single letter convention actually makes the use of generics
more obvious to me and easier to reason about. If I had to figure out
whether everything that looked like "Node" was a type parameter or a
concrete type I would be sad. [1]

-- Erik

[1] Before Scala I had no background in languages that had type
parameterization, so (as far as I can tell) I don't have an earlier
attachment to this style.

HamsterofDeath

unread,
Nov 17, 2011, 2:05:07 PM11/17/11
to scala-...@googlegroups.com
i have almost never seen a case where a single letter or letter + number wasn't enough. if you use a class with type parameters, you use actual types. if you are inside the class having the class parameters, you have to take a deeper look anyway or are the author and should know enough already. taking a quick glance at the declaration won't slow you down.

Michael Schmitz

unread,
Nov 17, 2011, 2:26:07 PM11/17/11
to Erik Osheim, Rex Kerr, Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
+1

Tony Morris

unread,
Nov 17, 2011, 2:42:08 PM11/17/11
to Matthew Pocock, scala-...@googlegroups.com

Write a few of your graph operations. Use the type parameters as if they were nodes or edges. Notice how you can't. The proposal is akin to projecting meaning onto universally quantified variables of a logical proposition. We say, paraphrased:

For all c such that c is an element of the set Cars...

Notice how we call the variable c, not car or any other particular meaning. Doing so would degrade readability to the extent that it may distract from the fact that this variable should contain no further context than its existence. The constraint of set membership is simply an application to an operation, no different to a list sort operation requiring ordering on its elements.

It is extremely important that type variable names contain no context (that is, call it what you want but I won't be projecting an imaginary context onto it). I am only motivated to point this out because one day someone is going to bring this point up IRL and I am going to have to deal with it. I don't want to; this elusive insight that I am apparently missing according to "the naming guys" is repeatedly shown to be a failed thesis and now it is crawling into the least welcome of places (type variables).

Please modify the thesis for practical purposes.

Simon Ochsenreither

unread,
Nov 17, 2011, 2:48:59 PM11/17/11
to scala-...@googlegroups.com, Rex Kerr, Matthew Pocock, tmo...@tmorris.net
D seems to prefix an ! to mark the difference between a type variable and a concrete type.

Matthew Pocock

unread,
Nov 17, 2011, 2:50:51 PM11/17/11
to Tony Morris, scala-...@googlegroups.com
Tony,

For normal programmers, names matter. Most people don't think in lambda calculus or category theory or first order predicate logic. These people need informative names.

Matthew

Matthew Pocock

unread,
Nov 17, 2011, 2:59:41 PM11/17/11
to Alex Repain, Michael Schmitz, Daniel Sobral, √iktor Ҡlang, tmo...@tmorris.net, scala-...@googlegroups.com
On 17 November 2011 18:34, Alex Repain <alex....@gmail.com> wrote:


2011/11/17 Matthew Pocock <turingate...@gmail.com>
Yes.... Wouldn't Map[K, V] or Map[Key, Value] be more self-explanatory? Peace.



There will always be people to not catch [K,V] as [Key, Value], and others to not catch what is Key or Value because they just don't know what a Map is (let's say the hereby example is easier than the general case).

The Map data structure is intrinsically associated with the concept of a data structure that represents some key instances drawn from a key set conforming to a Key type that 'map to' some value instances drawn from a value set/bag conforming to a Value type. If a person doesn't understand Key/Value (or K/V) because they don't know what a Map is, then they need to find out what a Map is. The issue you're raising in this case isn't with the naming of the type parameters, but that the entire concept modelled by the Map isn't known to the user. Once they understand the Map abstraction, it's much easer for a normal programmer to look at signatures with the type parameters Key/Value (or K/V) than A/B and associate this back to the Map abstraction. Normal people find names and mnemonics easier to remember than random letters. We can find any amount of published literature that demonstrates this experimentally, and probably also papers that specifically dissect out what sub-population this doesn't hold for (hint - this sub-population is not over-represented in that which is also your average programmer, certainly not to the point that you can discard using informative names in APIs aimed at average programmers).

Matthew

Tony Morris

unread,
Nov 17, 2011, 2:59:55 PM11/17/11
to scala-...@googlegroups.com
Are you seriously expecting me to buy this? That I, and others who
aspire to get practical work done, are not "normal programmers", while
you, and your buddies are? Is this how you justify your thesis to
yourself? Sorry, but it's pretty transparent to me.

Do you not think I have worked with people who were once "naming guys"?
They are wrong, so they tried every trick they had, like you are doing.
They're not "naming guys" anymore.

Either demonstrate the point (an appeal to normality/abnormality
exclusion is fallacious -- surely this is obvious) or work out that
you're making a mistake with adverse practical implications. All you've
got to do is use your Node/Edge type variables as if they were nodes or
edges. Let me know when you have achieved this.

>>> Matthew
>>>
>>>
>>>> --
>>>> Tony Morris
>>>> http://tmorris.net/
>>>>
>>>>
>>>>
>>>
>>> --
>>> Dr Matthew Pocock
>>> Integrative Bioinformatics Group, School of Computing Science, Newcastle
>>> University
>>> mailto: turingate...@gmail.com
>>> gchat: turingate...@gmail.com
>>> msn: matthew...@yahoo.co.uk
>>> irc.freenode.net: drdozer
>>> skype: matthew.pocock
>>> tel: (0191) 2566550
>>> mob: +447535664143
>>>
>>>
>


--
Tony Morris
http://tmorris.net/


Ken McDonald

unread,
Nov 17, 2011, 3:23:36 PM11/17/11
to scala...@googlegroups.com, scala-debate


On Thursday, November 17, 2011 6:51:01 AM UTC-6, Josh Suereth wrote:

Yet another thread that probably belongs on scala-debate.

AND to answer with my opinion :  I think using meaningful type parameter names can make sense, but there's a balance to be had.

Always there must be balance, young friend. (Yoda waves his light-saber).

OK, a number of people have recommended scala-debate as the proper forum for such ideas. I regard that as the "graveyard of ideas", and I try to put a lot of consideration into what I post so that I don't post about either minor or too-difficult-to-fix ideas. So what is the proper forum to someone who is novice/intermediate to Scala, and wants to post real concerns about the language that, by their own experience, could cause Scala to fail or do poorly? I would suggest that at the moment, there is not an adequate feedback mechanism from the real world as to what Scala needs to do to succeed.

And yes, I want to to succeed. I'm put a lot of time into it already, dagnabit!

Ken

Rex Kerr

unread,
Nov 17, 2011, 3:58:57 PM11/17/11
to scala-...@googlegroups.com, tmo...@tmorris.net, ykke...@gmail.com
Switched responses to -debate.

I think you're using the wrong criteria for -debate vs. -user.  -user is good for things that users care about and which they can employ.  -debate is good for things which need to be discussed and perhaps cannot be employed by users (because e.g. they're changes to the core library, and most users don't recompile their own core library).

On Thu, Nov 17, 2011 at 3:11 PM, Ken McDonald <ykke...@gmail.com> wrote:

1) Am I proposing an EASY solution (such as simply lengthening type variable names).

If it's a proposal for users to use longer type variable names, yes, it's easy.
 
2) Does this address a serious perceived problem with Scala (such as the corporate perception that Scala is "too complex")

It is _related to_ that discussion, I agree, but it is not obvious that it is a _solution_, nor that -users who really just want to give and receive information on how to use Scala would be widely interested.
 
3) Am I proposing something that is closed-ended,in the sense that it will not devolve into (somewhat :-) ) infinite debates over detail. In other words, am I presenting people with an easy choice? The goal of this last point is to avoid flame wars and indefinite posts back to the same subject. Such topics should definitely be in scala-debate.

The topic doesn't pass this criteron.  There is a significant component here that is normally addressed subjectively ("I like long names"), which makes for long debates.  Perhaps you were unaware that long names were disliked by a non-negligible number of people, at least for certain use cases; that's understandable and forgivable.
 
4) Does this address something that I, still a Scala novice, have found to be a genuine problem and believe would be a genuine problem in the broader world. I admit this is a subjective judgement, I do the best I can :-).

It addresses it, but may go the wrong way.  A giant incomprehensible block of text and symbols is no more comprehensible if replaced by an even more giant block (where text and/or symbols have been replaced with longer versions).

Another possible solution is to have a set of links on every collections class to useful resources: "Understanding Collection Types", "Collection Performance", "How to Extend a Collection", etc..

You might then start wishing That were named CB (C meaning "some collection" and B meaning--well, the same B as before), and CanBuildFrom was named Cbf:

  def ++[B >: A](elem: B)(implicit cbf: Cbf[Seq[A],B,CB])

Isn't that easy?  You take Seq[A], add a B to it, and get a CB?*

  def ++[NewElementType >: ExistingType](elem: NewElementType)(implicit cbf: CanBuildFrom[Seq[ExistingType],NewElementType,NewCollectionType])

It's self documenting, yes, but the flow of content has almost entirely been obscured.

Now, in the face of poor documentation, one may wish for the latter form since the type signature is a form of documentation.  (Not a very _good_ form of documentation, but it at least gets you thinking in some of the appropriate directions, while brief version may, to the uninitiated, motivate no thinking at all except WTF?)

But the solution is not to obscure program flow with long type names.  The solution is to provide easily accessible documentation.  If you know what it means, look at it and, presto! all the relevant information leaps out at you in a compact way.  If you don't know what it means, read the documentation, and presto! you can work your way through what is going on.
 
I am using myself as a proxy for a "new Scala user". I want Scala to succeed, so I believe that Scala problems that are SERIOUS problems for new users should be discussed in a mainstream group such as scala-user, not in a peripheral group such as scala-debate.

I appreciate your initiative in bringing up these issues.  But you have to keep in mind as a new user that while your perspective may reflect common problems of new users, your solutions may or may not be the best ones simply because you--thus far--lack the expertise necessary to appreciate the value of other solutions.  So even if your post elicited a whole bunch of "yeah!" and "+1" replies from other users, it wouldn't necessarily follow that your solution was a good one, or that further discussion on -user would lead to a good solution.  It _would_ mean that there was a major source of difficulty out there that should be addressed.

I think the solution is documentation, as I've argued, but I _don't_ think it is obvious that all Scala users really want to listen to and take part in that discussion.

  --Rex

* The downside of CB, of course, is that it makes you imagine that the collection _must_ have something to do with B.  For the majority of CanBuildFrom instances, this is true.  As far as the type constraints go, though, A could be String, B could be Option[Option[Boolean]],  and CB _could_ be Int.  In this sense, "That" is more honest.

nuttycom

unread,
Nov 17, 2011, 5:33:28 PM11/17/11
to scala-...@googlegroups.com, Tony Morris
"No true Scotsman" fallacy, please try again.

Matthew Pocock

unread,
Nov 17, 2011, 5:16:04 PM11/17/11
to tmo...@tmorris.net, scala-...@googlegroups.com
On 17 November 2011 19:59, Tony Morris <tonym...@gmail.com> wrote:
Are you seriously expecting me to buy this? That I, and others who
aspire to get practical work done, are not "normal programmers", while
you, and your buddies are? Is this how you justify your thesis to
yourself? Sorry, but it's pretty transparent to me.

You're self-evidently not a normal programmer. You care about types and correctness, but normal programmers care about writing the code and think about types afterwards, if at all. I am also not a normal programmer - I care a lot about performance, correctness and scoping/visibility. I've worked with and taught lots of normal programmers, and neither of us are that.
 
Either demonstrate the point (an appeal to normality/abnormality
exclusion is fallacious -- surely this is obvious) or work out that
you're making a mistake with adverse practical implications.

You've demonstrated no adverse practical implications of using informative names for type parameters - you've just appealed to their existence. Making bare assertions like this is fallacious. Can you show me, using Graph[N, E] as an example where we make incorrect assumptions about it if we think of N as Node and E as Edge, instead of an anonymous [A, B]? 

All you've
got to do is use your Node/Edge type variables as if they were nodes or
edges. Let me know when you have achieved this.

They become nodes or edges by virtue of their role in the graph. I'm not sure what other possible meaning there is to a node/edge in this context. It's a role they play, not something intrinsic to them. This role still needs naming, and the type parameter is the only place to name it.


Matthew

--
Tony Morris
http://tmorris.net/


Tony Morris

unread,
Nov 17, 2011, 6:11:23 PM11/17/11
to Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
On 11/18/2011 08:16 AM, Matthew Pocock wrote:


On 17 November 2011 19:59, Tony Morris <tonym...@gmail.com> wrote:
Are you seriously expecting me to buy this? That I, and others who
aspire to get practical work done, are not "normal programmers", while
you, and your buddies are? Is this how you justify your thesis to
yourself? Sorry, but it's pretty transparent to me.

You're self-evidently not a normal programmer. You care about types and correctness, but normal programmers care about writing the code and think about types afterwards, if at all. I am also not a normal programmer - I care a lot about performance, correctness and scoping/visibility. I've worked with and taught lots of normal programmers, and neither of us are that.

Come on mate, you can't expect me to accept this. There is no such thing as a "normal programmer." Of course I care about correctness (and therefore types), so does almost every programmer I know -- some just pay lip service to the idea and/or fumble around in the dark -- we all do to some extent.

It is not as if there is some trade; "I am a correctness guy while that other guy is a performance guy" -- WTF kind of nonsense is that? Sounds like something I might see on a recruiters website.


 
Either demonstrate the point (an appeal to normality/abnormality
exclusion is fallacious -- surely this is obvious) or work out that
you're making a mistake with adverse practical implications.

You've demonstrated no adverse practical implications of using informative names for type parameters - you've just appealed to their existence. Making bare assertions like this is fallacious. Can you show me, using Graph[N, E] as an example where we make incorrect assumptions about it if we think of N as Node and E as Edge, instead of an anonymous [A, B]?

You have named things Node/Edge. This is not a big deal *except you believe that your type parameters have something to do with graph nodes and edges*. You are absolutely wrong. It is not much of a leap to work out what adverse practical implications will happen from there -- you've just got to work out that you are wrong.



All you've
got to do is use your Node/Edge type variables as if they were nodes or
edges. Let me know when you have achieved this.

They become nodes or edges by virtue of their role in the graph. I'm not sure what other possible meaning there is to a node/edge in this context. It's a role they play, not something intrinsic to them. This role still needs naming, and the type parameter is the only place to name it.

I am not asking you to show me the existence of one (just one, only one) operation that supports your claim for no reason. It's because I know you will fail and it's not just that you will fail, but you will learn why you will fail. Then you will learn why you are wrong, then you will learn what adverse practical implications I allude to.

You're not going to get anywhere by dividing programmers into "us" and "them", unless you accept the division "people who are wrong about one thing" and "people who are not", but of course, this alone leads nowhere.

Tony Morris

unread,
Nov 17, 2011, 6:26:54 PM11/17/11
to Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
On 11/18/2011 09:22 AM, Matthew Pocock wrote:

On 17 November 2011 23:11, Tony Morris <tonym...@gmail.com> wrote:

You have named things Node/Edge. This is not a big deal *except you believe that your type parameters have something to do with graph nodes and edges*.

I honestly have no idea what you're driving at. def nodes: Set[Node] is semantically meaningful for a graph as Graph[Node, Edge]. def nodes: Set[Edge] is wrong. def incidentEdges(n: Node): Set[Edge] means something, and the type names are meaningful. The operations *define* what it is to be a graph node and edge. It's a role, not a type. There's no operation to perform on Node or Edge, only operations on Graph[Node, Edge].

You keep referring to data types.

Show me *operations* that use these type variables in a way that you claim has a context that exists.

class Graph[Node, Edge] {
  .. this bit
}

 
You are absolutely wrong. It is not much of a leap to work out what adverse practical implications will happen from there -- you've just got to work out that you are wrong.


Show me the mistake I'm encouraged to make by thinking of graphs over nodes and edges modelled by the type parameters Node and Edge that I would not make naming these parametrized types A, B.

You're misrepresenting what I already told you is the mistake. Shall I repeat it?

Matthew Pocock

unread,
Nov 17, 2011, 6:22:38 PM11/17/11
to tmo...@tmorris.net, scala-...@googlegroups.com
On 17 November 2011 23:11, Tony Morris <tonym...@gmail.com> wrote:

You have named things Node/Edge. This is not a big deal *except you believe that your type parameters have something to do with graph nodes and edges*.

I honestly have no idea what you're driving at. def nodes: Set[Node] is semantically meaningful for a graph as Graph[Node, Edge]. def nodes: Set[Edge] is wrong. def incidentEdges(n: Node): Set[Edge] means something, and the type names are meaningful. The operations *define* what it is to be a graph node and edge. It's a role, not a type. There's no operation to perform on Node or Edge, only operations on Graph[Node, Edge].
 
You are absolutely wrong. It is not much of a leap to work out what adverse practical implications will happen from there -- you've just got to work out that you are wrong.


Show me the mistake I'm encouraged to make by thinking of graphs over nodes and edges modelled by the type parameters Node and Edge that I would not make naming these parametrized types A, B.
 
Matthew
-- 
Tony Morris
http://tmorris.net/

Kenneth McDonald

unread,
Nov 17, 2011, 7:52:55 PM11/17/11
to scala-...@googlegroups.com, √iktor Ҡlang, Matthew Pocock, tmo...@tmorris.net
> trait Graph[Node, Edge] <--- Looks great to me

Except you just killed Node and Edge as trait/class names. At the very
least, I'd call them ANode and AnEdge.


Granted, but fairly minor (I think) in that I'm trying to encourage discussion about the deeper utility of meaningful names.

Ken 

Kenneth McDonald

unread,
Nov 17, 2011, 7:57:33 PM11/17/11
to scala-...@googlegroups.com, Matthew Pocock

It is extremely important that type variable names contain no context (that is, call it what you want but I won't be projecting an imaginary context onto it). I am only motivated to point this out because one day someone is going to bring this point up IRL and I am going to have to deal with it. I don't want to; this elusive insight that I am apparently missing according to "the naming guys" is repeatedly shown to be a failed thesis and now it is crawling into the least welcome of places (type variables).

Sorry Tony, but from a software engineering/maintainability point of view the statement that "type variable names contain no context" is just as crazy as (and no crazier than) the statement that "program variable names contain no context".  Code is intended to be used in a context, not matter how general (but as a general point, usually not too general). Names identify and anchor that context. This is _incredibly_ important to reusable software.

Ken

Tony Morris

unread,
Nov 17, 2011, 8:01:12 PM11/17/11
to scala-...@googlegroups.com
I will just point out the incredible weakness in your argument. Appealing to "that is crazy" cannot be taken seriously. No need to apologise -- it's not as if this is unusual.

Please think. You will hopefully then realise the transparency of your position. Do you honestly think you are portraying the limit of the depth of introspective thought on this matter? That I have somehow overlooked your constantly repeated position? There is some incredible deep insight being missed in this superficial mode of reasoning? Please allow me to apologise.

Think about the subject please, honestly and thoroughly.

Kenneth McDonald

unread,
Nov 17, 2011, 8:02:45 PM11/17/11
to scala-...@googlegroups.com, Matthew Pocock, tmo...@tmorris.net


On Thursday, November 17, 2011 12:45:56 PM UTC-6, Rex Kerr wrote:
On Thu, Nov 17, 2011 at 7:56 AM, Matthew Pocock <turingate...@gmail.com> wrote:
On 17 November 2011 12:11, Tony Morris <tonym...@gmail.com> wrote:
>
It is extremely important to pick meaningless names. The moment you
project meaning is the moment you start making all those mistakes that
we so often see.

Many times the types are not devoid of meaning. Consider:

trait Graph[A, B]

Bad.  Now I have to remember whether your graphs have nodes first or edges first.  I don't want to have to do that.
 
trait Graph[N, E]

Good!  Now I don't have to remember!
 
trait Graph[Node, Edge]

Why all the extra letters?  I already knew everything I needed to know.
 
I disagree completely. To you, these extra characters may be unneeded but harmless; to another, they may be vital. This is nothing more than that argument as to whether the loop counter should be n or loopCounter; IMHO, it should clearly be the latter (assuming you must do imperative programming.)

Why the freak are people so opposed to a few extra characters that don't even interfere with reading speed? (Humans read in phrases and words not in characters.)  just don't get it.

Ken 

Kenneth McDonald

unread,
Nov 17, 2011, 8:14:43 PM11/17/11
to scala-...@googlegroups.com, Matthew Pocock, Michael Schmitz, Daniel Sobral, √iktor Ҡlang, tmo...@tmorris.net

>>There will always be people to not catch [K,V] as [Key, Value], and others to not catch what is Key or Value because they just don't know what a Map is (let's say the hereby example is easier than >>the general case). Using A,B,C and so on is a way to force the API user to know his tool, to understand it, and to RTFDocumentation - of course yes, you'd better document your code if it uses >>abstract {type names} or value names. 

I don't normally condemn things out of hand, but this is simply the worst idea I've ever encountered in Comp. Sci. Literally, over 20 years of experience. Why not require that every function name be the min number of characters to uniquely represent it--that will certainly force programmers to read the f&*ckin API.

Where the h%^ll did this idea come from?

Ken

Kenneth McDonald

unread,
Nov 17, 2011, 8:20:09 PM11/17/11
to scala-...@googlegroups.com, tmo...@tmorris.net


On Thursday, November 17, 2011 1:59:55 PM UTC-6, Tony Morris wrote:
Are you seriously expecting me to buy this? That I, and others who
aspire to get practical work done, are not "normal programmers", while
you, and your buddies are? Is this how you justify your thesis to
yourself? Sorry, but it's pretty transparent to me.

Tony, you are not an the same galactic quadrant as a normal programmer. If I were a hiring manager evaluating you, I would put checks beside "brilliant", "highly productive", and some other related checkboxes, and then put in "reason for decline": "Not able to work effectively as part of a normal team."

Maybe I'm wrong. But everything I've seen about you on the net indicates both that you are probably worth about 10 normal programmers, and at the same time the code you produce would be completely unsupportable.

Ken

Artem Khodyush

unread,
Nov 17, 2011, 8:25:57 PM11/17/11
to scala-...@googlegroups.com, Matthew Pocock, Michael Schmitz, Daniel Sobral, √iktor Ҡlang, tmo...@tmorris.net
> Where the h%^ll did this idea come from?

You wonder where one-letter identifiers are constantly coming from ? Just go to arxiv.org and open any random math paper. 

You won't see any identifiers longer than 3 characters, but they are doing pretty good job with them for the last couple 
hundred of years :-)

Tony Morris

unread,
Nov 17, 2011, 8:29:16 PM11/17/11
to scala-...@googlegroups.com, Kenneth McDonald
On 11/18/2011 11:20 AM, Kenneth McDonald wrote:


On Thursday, November 17, 2011 1:59:55 PM UTC-6, Tony Morris wrote:
Are you seriously expecting me to buy this? That I, and others who
aspire to get practical work done, are not "normal programmers", while
you, and your buddies are? Is this how you justify your thesis to
yourself? Sorry, but it's pretty transparent to me.

Tony, you are not an the same galactic quadrant as a normal programmer. If I were a hiring manager evaluating you, I would put checks beside "brilliant", "highly productive", and some other related checkboxes, and then put in "reason for decline": "Not able to work effectively as part of a normal team."

You're just making more shit up dude. How on earth do you know this? I can absolutely guarantee you this wouldn't happen -- I have never got anywhere near this far in an interview with someone who holds these narrow-minded views.

Here is a funny story. I was once asked to "reverse a list in any programming language." The interview was for C# programming.

I said, "fold left with cons flipped beginning with nil" and I scribbled it in haskell. Here is the equivalent scala:

_.foldLeft(Nil)((a, b) => b :: a)

The interviewer went all ballistic with his departure from reality like you have done. I walked out. You narrow-minded interviewers think you have me on the ropes -- you don't. I won't be bullied like this.




Maybe I'm wrong. But everything I've seen about you on the net indicates both that you are probably worth about 10 normal programmers, and at the same time the code you produce would be completely unsupportable.

Ken

You say "completely unsupportable", yet you fail to recognise that this is a property of you, not the code and there is nothing I can do to the code to change it. The very idea that appeasing mediocrity yields some sort of pay-off is perpetuated only by mediocres -- good luck with that, but it's bullshit.

I especially love the quality of arguments presented for your position so far.

Kenneth McDonald

unread,
Nov 17, 2011, 8:30:15 PM11/17/11
to scala-...@googlegroups.com, Rex Kerr, Matthew Pocock, tmo...@tmorris.net

I find the single letter convention actually makes the use of generics
more obvious to me and easier to reason about. If I had to figure out
whether everything that looked like "Node" was a type parameter or a
concrete type I would be sad. [1]

-- Erik


I think I actually posted something about this in my original post. One of my points was (If I recall), are we not past the point where single-char type params are valuable?

Ken 

Russ P.

unread,
Nov 17, 2011, 9:10:53 PM11/17/11
to scala-debate
On Nov 17, 5:29 pm, Tony Morris <tonymor...@gmail.com> wrote:

> Here is a funny story. I was once asked to "reverse a list in any
> programming language." The interview was for C# programming.
>
> I said, "fold left with cons flipped beginning with nil" and I scribbled
> it in haskell. Here is the equivalent scala:
>
> _.foldLeft(Nil)((a, b) => b :: a)

aList.reverse

When do I start? 8^)

Kenneth McDonald

unread,
Nov 17, 2011, 9:47:32 PM11/17/11
to scala-...@googlegroups.com, Kenneth McDonald, tmo...@tmorris.net
Tony, I look forward to your book. I hope to learn a lot from it. But your really are "Sheldon" from "The Big Bang Theory", and I no longer consider it worthwhile to respond to your comments. The story you told about being asked how to to reverse a list in an interview, and your response to the interviewer, only reinforce to me (and I suspect others) how completely off the charts you are. (That's not intended as a compliment or an insult, or perhaps it's intended as both--you choose.)

Farewell,
Ken

Artem Khodyush

unread,
Nov 17, 2011, 10:13:25 PM11/17/11
to scala-...@googlegroups.com

> The story you told about being asked how to to reverse a list in an interview, and your response to the interviewer, only reinforce to me (and I suspect others) how completely off the charts you are

No, its the other way round. If you think that walking away after the interviewer rejects correct answer
is inappropriate response, I'm pretty sure there are lots of people here happy to be off your charts.

Tony Morris

unread,
Nov 17, 2011, 10:30:23 PM11/17/11
to scala-...@googlegroups.com, Kenneth McDonald, tmo...@tmorris.net
Yes, because a very straight-forward and efficient answer is totally
off-the-charts.

By the way, you have a huge selection bias. There really do exist people
who would also give a sensible answer to the question, and also endure
foolishness on behalf of the interviewer.

I suppose we should name our type variables then, because you are not
off the charts amirite?

Tony Morris

unread,
Nov 17, 2011, 10:32:55 PM11/17/11
to scala-...@googlegroups.com
On 11/18/2011 01:13 PM, Artem Khodyush wrote:

> The story you told about being asked how to to reverse a list in an interview, and your response to the interviewer, only reinforce to me (and I suspect others) how completely off the charts you are

No, its the other way round. If you think that walking away after the interviewer rejects correct answer
is inappropriate response, I'm pretty sure there are lots of people here happy to be off your charts.

Oh woops, now there are two of us!

Tony Morris

unread,
Nov 17, 2011, 10:37:07 PM11/17/11
to scala-...@googlegroups.com, Kenneth McDonald
On 11/18/2011 12:47 PM, Kenneth McDonald wrote:

PS: you might also like to know that your pseudo-psychological analysis,
likely influenced by pop culture while simultaneously having nothing to
do with reality, has real-life adverse impact on others. Just so you
know; something to think about, if you're into that. Thinking that is.
Try it.

Russ P.

unread,
Nov 17, 2011, 10:40:04 PM11/17/11
to scala-debate
On Nov 17, 7:13 pm, Artem Khodyush <green...@gmail.com> wrote:
> > The story you told about being asked how to to reverse a list in an
>
> interview, and your response to the interviewer, only reinforce to me (and
> I suspect others) how completely off the charts you are
>
> No, its the other way round. If you think that walking away after the
> interviewer rejects correct answer
> is inappropriate response, I'm pretty sure there are lots of people here
> happy to be off your charts.

Based on the information given I'd say that walking away in disgust is
not necessarily the best move in all such cases. What if it's a great
company but the interviewer just happens to be a jerk? I can't imagine
that interviewers are always the top talent at any company. What if
you really need the job? Wouldn't it make more sense to politely
explain the correctness of your answer to the interviewer?

--Russ P.

Tony Morris

unread,
Nov 17, 2011, 10:44:36 PM11/17/11
to scala-...@googlegroups.com

I should note that I did, in fact, explain how the solution works, but
when you are up against people who have difficulty divorcing themselves
from the idea of making up stupid shit and resort to unintentional
bullying in order to give themselves the illusion of the legitimacy of
their position, you must make a prognostic assessment about the
effectiveness of continuing.

Many interviewers think they have some kind of upper-hand by virtue of
being the interviewer. They don't; it's an illusion. I certainly don't
want to be working with immutable idiocy or bullies.

Knowledge is not for everyone. Pick your battles.

Artem Khodyush

unread,
Nov 17, 2011, 10:45:32 PM11/17/11
to Russ P., scala-debate

> What if it's a great company but the interviewer just happens to be a jerk? 
> I can't imagine that interviewers are always the top talent at any company.

Well it of course depends on how high (or low) you value yourself. But if the
company tolerates people who don't behave professionally when doing
interviews (are being jerks, in other words), that's not a good sign.

Tony Morris

unread,
Nov 17, 2011, 10:54:52 PM11/17/11
to scala-...@googlegroups.com
On 11/18/2011 01:40 PM, Russ P. wrote:

Walking away due to poor prognosis of making sense is distinct to
walking away in disgust.

It's not always emotional dude, promise. Sometimes it's just what makes
a bit of fucking sense.

Rex Kerr

unread,
Nov 17, 2011, 11:05:37 PM11/17/11
to scala-...@googlegroups.com, Matthew Pocock, tmo...@tmorris.net
On Thu, Nov 17, 2011 at 8:02 PM, Kenneth McDonald <ykke...@gmail.com> wrote:


On Thursday, November 17, 2011 12:45:56 PM UTC-6, Rex Kerr wrote:
On Thu, Nov 17, 2011 at 7:56 AM, Matthew Pocock <turingate...@gmail.com> wrote:

On 17 November 2011 12:11, Tony Morris <tonym...@gmail.com> wrote:
>
It is extremely important to pick meaningless names. The moment you
project meaning is the moment you start making all those mistakes that
we so often see.

Many times the types are not devoid of meaning. Consider:

trait Graph[A, B]

Bad.  Now I have to remember whether your graphs have nodes first or edges first.  I don't want to have to do that.
 
trait Graph[N, E]

Good!  Now I don't have to remember!
 
trait Graph[Node, Edge]

Why all the extra letters?  I already knew everything I needed to know.
 
I disagree completely. To you, these extra characters may be unneeded but harmless; to another, they may be vital.

Anyone who doesn't know that graphs are made up of nodes and edges should stay far, far away from a graph library until they take some graph theory.
 
This is nothing more than that argument as to whether the loop counter should be n or loopCounter; IMHO, it should clearly be the latter (assuming you must do imperative programming.)

Yes, this is very similar.  The extra ten characters are just visual clutter.  Which is easier to understand at a glance:
  for (n <- 1 to 10) a(n+1) = a(n) + a(n-1)
or
  for (n <- 1 to 10) a(loopCounter+1) = a(loopCounter) + a(loopCounter-1)
 
Why the freak are people so opposed to a few extra characters that don't even interfere with reading speed?

Because they do interfere with reading speed.  I'm not reading "loopCounter" alone, I'm reading a(n+1).  Instead of reading the whole operation, like a*b + c, in one go, I have to parse each word.

I don't object out of some fit of pique.  I object because it gets in the way of grasping the concept quickly, both visually and conceptually.  It's like touch-typing.  You could argue that the keyboard should be laid out ABCDEFG... because it's so much easier for people who look at the keys.  Also, people don't type words, they type letters, so what's the big deal about using one finger at a time?

There is a place for longer variable names, but I don't think index variables or generic types (which serve a similar role) are the place.

  --Rex

Cédric Beust ♔

unread,
Nov 17, 2011, 11:05:29 PM11/17/11
to Artem Khodyush, scala-...@googlegroups.com

On Thu, Nov 17, 2011 at 7:13 PM, Artem Khodyush <gree...@gmail.com> wrote:
No, its the other way round. If you think that walking away after the interviewer rejects correct answer
is inappropriate response

We lack context to determine if the answer was correct. If the question specified that the answer should be provided in a language other than Haskell, then the answer is indeed incorrect.

At any rate, the interviewer should certainly not go ballistic over this, acknowledge that the answer is technically correct and then press on for the candidate to write it again in one of the expected languages.

I would certainly walk out of any interview where the interviewer goes ballistic on me, regardless of the topic being discussed, but then again, I'm not surprised to hear (again) this anecdote coming from Tony.

-- 
Cédric


 

Tony Morris

unread,
Nov 17, 2011, 11:07:46 PM11/17/11
to scala-...@googlegroups.com
The context, as originally stated, was to reverse a list in any programming language.

Stefan Wagner

unread,
Nov 17, 2011, 11:37:07 PM11/17/11
to scala-debate
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am 17.11.2011 15:47, schrieb Matthew Pocock:
> Hi,
>
> Agreed. I have type parameters rendered in italic and type alases as
> italic+bold in intellij idea. I'm not a fan of Christmas-tree highlighting,
> but this seems to help.

+1 for Christmas-tree highlighting :) (let's abbr. it to CTH).

Maybe we should start a feature request for jline, for CTH in the REPL.

- --

Tschööö--->...Stefan
- ---------------------------
Don't visit my homepage at:
http://home.arcor-online.net/hirnstrom
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk7F4PMACgkQQeATqGpDnRoELQCfezBzGfJJXzN6smxmSJM9ud0x
0OIAn3ztlqT82q4L9syY5Xh4n8lPn2j3
=2sEO
-----END PGP SIGNATURE-----

Erik Osheim

unread,
Nov 17, 2011, 11:55:54 PM11/17/11
to Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
On Thu, Nov 17, 2011 at 11:22:38PM +0000, Matthew Pocock wrote:
> Show me the mistake I'm encouraged to make by thinking of graphs over nodes
> and edges modelled by the type parameters Node and Edge that I would not
> make naming these parametrized types A, B.

I don't want to put words in Tony's mouth but I will try to explain
what I think he is getting at.

Let's say you've written a class like so:

class DirectedGraph[Node, Edge](nodes:Set[Node], edges:Set[Edge]) {
...
def hasEdge(src:Node, dst:Node): Boolean = ...
}

(You could argue that you only need the edges in the constructor... it
doesn't really make a difference for this example.)

The point is, how do you implement hasEdge? Clearly we know that any
type representing an edge in a directed graph needs to store two nodes:
a source and a destination. But our type parameter allows us to pass
*any* type as "Edge". Graph[Int, Int] is a seemingly valid type (the
type system permits it and it would compile) but I don't see any
obvious way to use Int as an edge, especially with a totally
independent Node type parameter.

If you are stubborn and want to keep using type params but get things
working I think you'll find yourself using context bounds and doing
something like this:

trait Node
trait Edge[NodeType <: Node] {
val src:NodeType
val dst:NodeType
def equiv(src2:NodeType, dst2:NodeType) = src == src2 && dst == dst2
}
class Graph[NodeType <: Node, EdgeType <: Edge[NodeType]](nodes:Set[NodeType], edges:Set[EdgeType]) {
...
def hasEdge(src:NodeType, dst:NodeType): Boolean = {
edges.filter(_.equiv(src, dst)).isEmpty
}
}

...or something like this.

The point is that the whole example of a graph with type parameters for
nodes and edges is totally confused. Generic type parameters are
defined or explicated by the constraints put on them. "Node" and "Edge"
are useful descriptors for the constraints that make guarantees about
node/edge behavior (for example, the type which guarantees that edges
have a src node and dst node). I have a hard time imagining someone
seeing "NodeType <: Node" and finding it less confusing than something
like "T <: Node".

In the graph case, the type parameter doesn't really give you anything
over a normal OO graph example. If anything, a type parameter should be
used to give nodes a "payload" (e.g. a number, a string, and object)
that is stored in the graph. Here's a naive example of what I mean:

case class Node[T](payload:T)
case class Edge[T](src:Node[T], dst:Node[T])
case class Graph[T](nodes:Set[T], edges:Set[T]) {
def hasNode(node:Node[T]) = nodes.contains(node)
def hasEdge(src:Node[T], dst:Node[T]) = edges.contains(Edge(src, dst))
...
}

Since graphs are a data structure for storing data (like List) it makes
sense to me that you'd want to define Graph[T], not Graph[N, E]. I
think this is why Tony was asking you to provide the graph
implementation--because once you start it quickly seems incoherent.
Maybe you imagined something other than the examples I provided--I
can't imagine it making sense, but maybe I have missed the point
instead.

There are lots of examples of OO graph implementations as well as a
Scala implementation using inner types, so it should be easy to compare
those to an approach using something like Graph[Node, Edge].

Hope this was helpful. I'm certainly not saying either of my
implementations is the "only way to do it" but I think this is the
point that Tony and others were trying to make.

-- Erik

Tony Morris

unread,
Nov 18, 2011, 12:03:01 AM11/18/11
to scala-...@googlegroups.com
Type parameters are not just parameters like method parameters. The problem with projecting names onto type parameters, unlike method parameters, it that this departure from reality is *always* unwelcome (unlike coincidentally having no impact for method parameters). That is, you will always be wrong by virtue of them actually being universally quantified variables. You will never be right. There doesn't exist a case where projecting anything but "forall" onto a type parameter (in position of universal quantification) is sensible.

Always happy to prove any code incorrect, as a predictable consequence of continued subscription to these illusions.

On 11/18/2011 02:55 PM, Josh Suereth wrote:
>
> Guys, it seems The utility of this discussion has declined. Let's refrain from bloodying noses by continuing in the current vein.
>
> I'll throw something out there.
>
> Type parameters *are parameters * just like method parameters. If you think method parameters require a certain naming style, it is probably worthwhile to use this on type parameters.
>
> If a type parameter looks like a class/type, that's similar to a method parameter looking like a member / term. Notice the adjustments to the unofficial style guide for this.

>
> On Nov 17, 2011 11:39 PM, "Stefan Wagner" <hirn...@arcor.de <mailto:hirn...@arcor.de>> wrote:
>

Am 17.11.2011 15:47, schrieb Matthew Pocock:
> Hi,

> Agreed. I have type parameters rendered in italic and type alases as
> italic+bold in intellij idea. I'm not a fan of Christmas-tree highlighting,
> but this seems to help.

+1 for Christmas-tree highlighting :) (let's abbr. it to CTH).

Maybe we should start a feature request for jline, for CTH in the REPL.


Artem Khodyush

unread,
Nov 18, 2011, 12:15:50 AM11/18/11
to Josh Suereth, Stefan Wagner, scala-debate
> Type parameters *are parameters *  just like method parameters

Yes and no. Method parameters have a type, type parameters
can have constraints but often don't.

A type parameter without constraints is like a method parameter 
of type 'Any'. When you are trying to assign meaningful names 
to them you end up doing something like

def substring(str: Any, startPos: Any, endPos: Any)

which is good indicator that you are doing something wrong.



On Thu, Nov 17, 2011 at 8:55 PM, Josh Suereth <joshua....@gmail.com> wrote:

Guys,  it seems The utility of this discussion has declined.   Let's refrain from bloodying noses by continuing in the current vein.

I'll throw something out there.

Type parameters *are parameters *  just like method parameters.   If you think method parameters require a certain naming style, it is probably worthwhile to use this on type parameters.

If a type parameter looks like a class/type, that's similar to a method parameter looking like a member / term.   Notice the adjustments to the unofficial style guide for this.

Josh Suereth

unread,
Nov 17, 2011, 11:55:59 PM11/17/11
to Stefan Wagner, scala-debate

Guys,  it seems The utility of this discussion has declined.   Let's refrain from bloodying noses by continuing in the current vein.

I'll throw something out there.

Type parameters *are parameters *  just like method parameters.   If you think method parameters require a certain naming style, it is probably worthwhile to use this on type parameters.

If a type parameter looks like a class/type, that's similar to a method parameter looking like a member / term.   Notice the adjustments to the unofficial style guide for this.

On Nov 17, 2011 11:39 PM, "Stefan Wagner" <hirn...@arcor.de> wrote:

Stefan Wagner

unread,
Nov 18, 2011, 12:46:33 AM11/18/11
to scala-...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am 17.11.2011 23:16, schrieb Matthew Pocock:

> You're self-evidently not a normal programmer. You care about types and
> correctness, but normal programmers care about writing the code and think
> about types afterwards, if at all.

Then I'm not a normal programmer too. You can't seriously think, that
paramters match for 'normal' programmers accidentally, do you?

> They become nodes or edges by virtue of their role in the graph. I'm not
> sure what other possible meaning there is to a node/edge in this context.
> It's a role they play, not something intrinsic to them. This role still
> needs naming, and the type parameter is the only place to name it.

That makes much more sense than to me, than the first paragraph.
Although - if Tony rejects such claims, my experience so far tells me,
that he does so with good reason.

Last year, I tried to solve the 99-scala-puzzles, which contained a
section of interesting tree-puzzles. As a *normal* programmer, who
didn't study informatics, I wasn't bored, because I hadn't much to do
with trees before, while programming. To solve the puzzles, I didn't
needed an Edge-class/-trait. My key element was a trait LR, which was
named LeftRight in the beginning, but I used it so often, that I rapidly
shortened the name to LR.
With l: Option[LR] and r: Option[LR] I defined the methods 'depth',
'preorder', 'inorder' and 'postorder', but while implementing, most of
the intermediate LRs vanished to nowhere. I didn't have an Edge, but a
case class Node and Leaf and object Node.

My abstract classs Tree extended LR, but used LR very rarely.

The complicated thing about it was the inheritance question; the
signature was:

abstract class TTree [+T <% Ordered[T]] extends LR { /...
and part of time I found myself in wild experimenting, how to make that
... compile. There are some T and U which could have been named PAYLOAD
or ELEMENT or E, but T seemed appropriate as well, and after T, there
comes U. Now I look at them, and they have no meaning, beside being the
content, which is put into that Tree.

LR is of course something like a Node, but I use it as a trait, not as a
type declaration. In the end, it is only the payload, which is encoded
by a Type-identifier (T, U) which has nearly no meaning.

It is like the Banana in the List of Bananas - the Banana doesn't help
in understanding the List.


- --

Tschööö--->...Stefan
- ---------------------------
Don't visit my homepage at:
http://home.arcor-online.net/hirnstrom
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk7F8TkACgkQQeATqGpDnRrqnACgjvMYlRpct2YFB6wAn+DSR0xZ
OzAAn3t/kQL6I3aA6xLSOe0YF1gy3F3A
=T8wM
-----END PGP SIGNATURE-----

Josh Suereth

unread,
Nov 18, 2011, 8:55:08 AM11/18/11
to Artem Khodyush, Stefan Wagner, scala-debate

Type parameters have kinds.  Method parameters have types.   I don't see any value to your logic.

This is like saying if I accept a method of type Any,  then its name is meaningless.

Matthew Pocock

unread,
Nov 18, 2011, 9:00:07 AM11/18/11
to Erik Osheim, tmo...@tmorris.net, scala-...@googlegroups.com
On 18 November 2011 04:55, Erik Osheim <er...@plastic-idolatry.com> wrote:
On Thu, Nov 17, 2011 at 11:22:38PM +0000, Matthew Pocock wrote:
> Show me the mistake I'm encouraged to make by thinking of graphs over nodes
> and edges modelled by the type parameters Node and Edge that I would not
> make naming these parametrized types A, B.
 
Let's say you've written a class like so:

 class DirectedGraph[Node, Edge](nodes:Set[Node], edges:Set[Edge]) {
   ...
   def hasEdge(src:Node, dst:Node): Boolean = ...
 }

(You could argue that you only need the edges in the constructor... it
doesn't really make a difference for this example.)

The point is, how do you implement hasEdge?

Well, you can't with that concrete implementation of a directed graph. You could, however, implement it with:

class DirectedGraph[Node, Edge](nodes: Set[Node], edges: Map[Edge, (Node, Node)]) {
  ...
}

If you model the graph like this, the nodes and edges can be any type, as it is the graph instance that is entirely responsible for storing the graph's topology. I'm not claiming that this is an efficient, or even a desirable way to represent a directed graph, but it will work. All queries about the topology must be answered by refering to the Graph instance. Different graphs over the same node and edge instances may return different answers, just as the question: who is your mother? is different for different people. Having topology associated directly with nodes or edges would be like having a Map implementation where the key knew its value.
 
Clearly we know that any
type representing an edge in a directed graph needs to store two nodes:
a source and a destination.

Usually, I want to be able to generate many graphs over the same node and edge instances (or perhaps unique node/edge labels?). So, let's re-write the above type to reflect the labelled nature of the graph and introduce some qua types:

class DirectedGraph[NodeLabel, EdgeLabel](...) {
  type Node = { ... some operations that capture the enclosing graph instance, so we can say e.g. node.incidentEdges
                       def label: NodeLabel
                     }
  type Edge = { ... some operations that capture the enclosing graph instance, so we can say e.g. edge.from, edge.to
                       def label: EdgeLabel
                    }
}

It's personal preference as to if you like working with the qua instances or always operate via the graph.
 
If you are stubborn and want to keep using type params but get things
working I think you'll find yourself using context bounds and doing
something like this:

 trait Node
 trait Edge[NodeType <: Node] {
   val src:NodeType
   val dst:NodeType
   def equiv(src2:NodeType, dst2:NodeType) = src == src2 && dst == dst2
 }
 class Graph[NodeType <: Node, EdgeType <: Edge[NodeType]](nodes:Set[NodeType], edges:Set[EdgeType]) {
   ...
   def hasEdge(src:NodeType, dst:NodeType): Boolean = {
    edges.filter(_.equiv(src, dst)).isEmpty
   }
 }

...or something like this.

Yeah, I've seen this a lot. It's nasty. I've never managed to make any API like this scale to large datasets or many persistent operations.

Hope this was helpful. I'm certainly not saying either of my
implementations is the "only way to do it" but I think this is the
point that Tony and others were trying to make.

Then I think the point was lost due to mutual incomprehension - I had assumed the graph was modeled as a type-class where instances of this type-class contained all the knowledge about the topology of the graph and no knowledge is stored directly on the nodes or edges.

Matthew
 

-- Erik



--
Dr Matthew Pocock
Integrative Bioinformatics Group, School of Computing Science, Newcastle University
skype: matthew.pocock
tel: (0191) 2566550

Chris Marshall

unread,
Nov 18, 2011, 10:31:53 AM11/18/11
to turingate...@gmail.com, viktor...@gmail.com, scala-...@googlegroups.com
That's odd - Map[A, B] extends A => B. Thinking about K's and V's might have blinded you to that fact


Date: Thu, 17 Nov 2011 19:59:41 +0000
Subject: Re: [scala-debate] Re: [scala-user] Time to encourage meaningful type parameter names? Discuss
From: turingate...@gmail.com

The Map data structure is intrinsically associated with the concept of a data structure that represents some key instances drawn from a key set conforming to a Key type that 'map to' some value instances drawn from a value set/bag conforming to a Value type

Rex Kerr

unread,
Nov 18, 2011, 11:06:46 AM11/18/11
to Chris Marshall, turingate...@gmail.com, viktor...@gmail.com, scala-...@googlegroups.com
On Fri, Nov 18, 2011 at 10:31 AM, Chris Marshall <oxbow...@hotmail.com> wrote:
That's odd - Map[A, B] extends A => B. Thinking about K's and V's might have blinded you to that fact

Why did you choose A and B there?  A and B don't scream out "function" to me.  Function1 uses T1 and R.  Map[K,V] extends K => V is equally informative.  If you had Map[T1,R], that might provoke some serious head-scratching--T1?  R?  What?  Why are they named _that_ way instead of something obvious or utterly generic?

But the real drawback is that the fraction of time you care that Map extends Function1 is small compared to the fraction of the time that you care where the key is and where the value is.

It's not like names have no point at all.  We forget things; if we always remembered, we wouldn't need type checking.  Otherwise, we could just declare

abstract class A[B] {
  def b[C](c: B => C): A[C]
  def e(f: B): B
  def g[D](h: D)(i: B => D): D
}

which one can figure out uses for by pondering the type signatures.  Just because one can take the opposite approach of overly-long and overly-specific names and end up with something even more atrocious (to my mind):

abstract class WrapperForSomethingThatMayNotExist[TypeOfThingThatMayNotExist] {
  def transformWithFunctionIfPresent(
    transformerFunction: TypeOfThingThatMayNotExist => TypeToTransformTo
  ): WrapperForSomethingThatMayNotExist[TypeToTransformTo]
  def getWrappedObjectIfPresentOrDefaultIfNot(
    defaultValue: TypeOfThingThatMayNotExist
  ): TypeOfThingThatMayNotExist
  def getTransformedValueIfThingExistsOrDefaultIfNot[TypeOfThingToTransformToOrReturn] (
    defaultValue: TypeOfThingToMapToOrReturn
  ) (
    transformerFunction: TypeOfThingThatMayNotExist => TypeOfThingToTransformToOrReturn
  ): TypeOfThingToTransformToOrReturn
}

does not mean that meaningless names are ideal.

Compact but mnemonically useful names are the way to go.

  --Rex
 

Knut Arne Vedaa

unread,
Nov 17, 2011, 9:53:44 AM11/17/11
to scala-...@googlegroups.com
On 17.11.2011 15:03, √iktor Ҡlang wrote:
> "The" can be dropped since it cannot be anything else.
> "Type" can be dropped since it can only be a type, you don't write: "val
> theThingVal = new Thing"
>
> trait Graph[Node, Edge] <--- Looks great to me

Since it's convention to have type names start with an upper case
letter, and variables (and function parameters) with a lower case
letter, and type parameters being one or two or maybe three upper case
letters, a quick glance at the above would lead me (at least) to think
that Node and Edge are types instead of type parameters. And since that
doesn't make sense in the context, there might be some initial cognitive
dissonance - at least there was for me. :)

I think

trait Graph[nodeType, edgeType]

is more readable.

Knut Arne Vedaa

Rex Kerr

unread,
Nov 18, 2011, 11:52:20 AM11/18/11
to Knut Arne Vedaa, scala-...@googlegroups.com
On Thu, Nov 17, 2011 at 9:53 AM, Knut Arne Vedaa <kav...@gmail.com> wrote:

I think

trait Graph[nodeType, edgeType]

is more readable.

Argh, now they look like regular variables, not something to do with types!

trait Graph[NODE, EDGE]

is visually annoying, but the intent should be unambiguous.

  --Rex

Artem Khodyush

unread,
Nov 18, 2011, 12:25:00 PM11/18/11
to Josh Suereth, Stefan Wagner, scala-debate

> This is like saying if I accept a method of type Any,  then its name is meaningless.

Yes it is meaningless because you can't do anything meaningful with Any. To begin
with, there aren't that many useful methods that take Any. Let's look at one:

 override def equals(that: Any) = that match { 
...
 } 

Note how it's immediately begins with the code that figures out at run time 
what 'that' means, and you can make a good guess what the code does
based on the method name, but parameter name is utterly irrelevant.

The same goes for unconstrained type parameters - there are always
better and explicit ways to express their meaning than encoding it in
names and hoping for people to follow conventions.



 , except
for calling methods like equals, toString, and hashCode, defined by mistake 
in the root object. In fact, ideally there should't be any value of type Any mentioned
in statically checked program.

Types, on the other hand, 

Artem Khodyush

unread,
Nov 18, 2011, 1:26:51 PM11/18/11
to Josh Suereth, Stefan Wagner, scala-debate

Oops sorry I send almost finished draft - please ignore the last paragraph which
starts with a comma and does not make sense anyway.

Michael Schmitz

unread,
Nov 18, 2011, 3:36:30 PM11/18/11
to Erik Osheim, Matthew Pocock, tmo...@tmorris.net, scala-...@googlegroups.com
Thanks for this clear explanation. You convinced me to change an
implementation from Graph[V] to Graph[T]. Even though I don't attempt
an implementation like the one you describe below (Graph[V, E]), I did
often consider V as a vertex instead of the *data that is stored in a
vertex*. It shows in my implementation.

Peace. Michael

Philippe Lhoste

unread,
Nov 19, 2011, 4:46:38 AM11/19/11
to scala-...@googlegroups.com
On 18/11/2011 01:57, Kenneth McDonald wrote:
> Sorry Tony, but from a software engineering/maintainability point of
> view the statement that "type variable names contain no context" is just
> as crazy as (and no crazier than) the statement that "program variable
> names contain no context". Code is intended to be used in a context, not
> matter how general (but as a general point, usually not too general).
> Names identify and anchor that context. This is _incredibly_ important
> to reusable software.

I have to disagree, at least partially, here. Some software is highly
reusable just because they don't have a context...
I barely know Scalaz, mostly from what I have read here and there, but
my understanding is that it is very abstract, disconnected from specific
domains ("business logic"). Yet people find it very useful, because they
mastered the mechanisms it offers, and find them very useful when
applied to *their* business logic.
Somehow, it seems like a kind of meta-programming, offering tools to be
used in a more specific domain.

I see this kind of tool as highly reusable, yet without identity.
Somehow, it is similar for the collection library.

Of course, you can still name (semi-)abstract stuff, like "the thing we
iterate on", "the type of the cumulated result" or such.
Of course, in some domains, the names can draw on the underlying theory:
nodes and edges in graph theory, key and values in data maps, and so on.
But overall, specific names can get in the way.

Perhaps what is missing from the Scala doc is context. Somehow, it lists
together several methods but description is short, context can be
missing, etc.

I don't think the tradition of one letter type names will go away, but
in a few entries of ScalaDoc I looked at, the types are (succinctly)
explained in the Scala doc itself. So even if the names aren't very
explicit, the doc is here.

--
Philippe Lhoste
-- (near) Paris -- France
-- http://Phi.Lho.free.fr
-- -- -- -- -- -- -- -- -- -- -- -- -- --

Josh Suereth

unread,
Nov 19, 2011, 1:33:22 PM11/19/11
to Philippe Lhoste, scala-...@googlegroups.com
People ascribe names to abstract things all the time.   When I say "fire", I may be referring to all my experiences of fire as an abstract concept.  Your mind interrupts it and ascribes the aspects of fire that it knows to the words I am using.

The same is true with names.  To Say that the more abstract a thing, the less important the name is BOGUS, bunk.   WHY oh why to we ascribe silly names to abstract concepts like:

Monad
Monoid
Eigenvector
Nullspace
monomorphism
Jacobian

My opinion is that the more abstract a concept, usually the longer or sillier the name (probably because they're named after the person who first *described* the abstract concept).

You see, if I give something a name and a description, I can start using the name in place of the description.   This is what language is all about. 

Graph[N,V] may be poor, but Graph[NodeData,VertixData] doesn't seem poor to me at all.  Again, I can come up with a class Graph where these names make a *lot* of sense.

Even in the case of "def equals(that: Any): Boolean", we still use "that" or "rhs" instead of "x" or "y", Where "that" refers to "something that is not htis" and "rhs" refers to the right-hand-side of an expression.   These words connote *meaning* and only as much meaning as needed to determine what the variable is doing.


trait TypeFunctor {
  type F[x]
  def map[X, Y](f: X => Y): F[X] => F[Y]
}

To those who don't understand the concepts of functors, these names are pretty poor.  However, if I *document* the concepts I'm using.

/** A type functor is a mapping between two categories of types.   A functor can take any type in the first category and
 * map it onto a second category (of still types). 
 */
trait TypeFunctor {
  /** This type constructor is used to map any type from the initial category (of all possible types) into another category
   * (that may or may not consist of all types).
   * @tparam X  The type to be mapped into the new category
   * @return  The type in the second category.
   */
  type F[X]
  /**
   *  This method takes  a type morphism (an arrow between points A and B in the initial category.  
   *  Note: A morphism in types is a function that can convert elements of type A into type B).
   *  The type morphism is mapped it into the new category defined by the functor.
   *  defined by this functor.
   *
   *  @tparam A  The initial type of the input morphism.
   *  @tparam B  The final type of the input morphism
   *  @param f  The morphism (function) that can map elements of type A into type B
   *  @returns  A morphism that can take values in the mapped category of this functor.
   */
  def map[A, B](f: A => B): F[A] => F[B]
}

NOW, I've given *descriptions* to my abstract types.   Now when people see "A" and "B" in the context of the class, there's a bit of meaning attached to the names, which are accurate.   When I use "F[?]" in later code, I've defined what F is in my source code, so users can understand it.

Scalaz is the *most* disappointing library in the scala ecosystem due to it's lack of documentation and poor naming choice.  If you wish others to understand an abstract concept, you need to provide a description for that concept.   Until you do so, it's just meaningless gibberish.  Scalaz *still* suffers from this, despite good efforts from some.  Claiming that abstract concepts are "lessened' through good names and documentation is bunk, bogus and disappointing to find.

One *could* argue that the source code is the description used for the name.  I could use this excuse to have horrible names throughout my codebase, even if a well known name was available and would help ease someone's ability to learn the concepts in my library.   I don't buy it.

So, as in all things, *naming* is difficult.   A poor name can convey the *wrong* meaning.   However, conveying *no* meaning is perhaps just as poor.   If you're going to use an abstract name (like X or A) for something, please document a description if possible.    If the variable has no meaning to be conveyed, then why is it in your source code?

Even non-english words like "Oooga Booga" convey some meaning.

- Josh

Randall R Schulz

unread,
Nov 19, 2011, 4:19:14 PM11/19/11
to scala-...@googlegroups.com
On Thursday 17 November 2011, Kenneth McDonald wrote:
> .... Why not require that every function name be the
> min number of characters to uniquely represent it-- ...

Please show us how to quantify "... the min number of characters
[required] to uniquely represent [every function]."

And tell us how that relates to the concept of functional abstraction.


> Ken


Randall Schulz

Cédric Beust ♔

unread,
Nov 19, 2011, 7:14:39 PM11/19/11
to Josh Suereth, Philippe Lhoste, scala-...@googlegroups.com
Josh, that was... beautiful.

-- 
Cédric

Kenneth McDonald

unread,
Nov 19, 2011, 7:54:13 PM11/19/11
to scala-...@googlegroups.com
I was assuming that the number of functions are known (or at least bounded), in which case the calculation is trivial.

The observation was intended semiseriously...why represent _anything_ with a number of characters greater than that necessary to guarantee a unique representation? Obviously, because further characters can add (for lack of a better term) meta-semantic meaning.

Ken

Kenneth McDonald

unread,
Nov 19, 2011, 7:56:59 PM11/19/11
to scala-...@googlegroups.com, Matthew Pocock, tmo...@tmorris.net
I have no referral to the referred-to article. Nonetheless I will put myself out on a limb: Prefixing interfaces with I is perfectly valid if the mental payback is greater than the cost. As (I believe) it is in Java, but (for obvious reasons) is not in Scala.

Ken

Kenneth McDonald

unread,
Nov 19, 2011, 7:59:04 PM11/19/11
to scala-...@googlegroups.com, Daniel Sobral, √iktor Ҡlang, Matthew Pocock, tmo...@tmorris.net
Looked it up. Simply an entry in the Scaladoc docs, and I don't see that is has any relevance to the current discussion.

Ken

Kenneth McDonald

unread,
Nov 19, 2011, 8:02:10 PM11/19/11
to scala-...@googlegroups.com, Matthew Pocock, Daniel Sobral, √iktor Ҡlang, tmo...@tmorris.net
OK, if you're willing to go with Map[K, V], why not Map[Key, Value]. _Vastly_ more descriptive, not much longer, much more helpful to the newcomer, not any signficant drawback to the experienced.

Ken

Kenneth McDonald

unread,
Nov 19, 2011, 8:07:27 PM11/19/11
to scala-...@googlegroups.com, Alex Repain, Michael Schmitz, Daniel Sobral, √iktor Ҡlang, tmo...@tmorris.net
The Map data structure is intrinsically associated with the concept of a data structure that represents some key instances drawn from a key set conforming to a Key type that 'map to' some value instances drawn from a value set/bag conforming to a Value type. If a person doesn't understand Key/Value (or K/V) because they don't know what a Map is, then they need to find out what a Map is. The issue you're raising in this case isn't with the naming of the type parameters, but that the entire concept modelled by the Map isn't known to the user. Once they understand the Map abstraction, it's much easer for a normal programmer to look at signatures with the type parameters Key/Value (or K/V) than A/B and associate this back to the Map abstraction. Normal people find names and mnemonics easier to remember than random letters. We can find any amount of published literature that demonstrates this experimentally, and probably also papers that specifically dissect out what sub-population this doesn't hold for (hint - this sub-population is not over-represented in that which is also your average programmer, certainly not to the point that you can discard using informative names in APIs aimed at average programmers).

Again, I disagree. At some point I may have to look it up, but basically, it takes no more cognitive processing to understand "Value" as "Value" than it does to understand "V" as "Value". Probably even less. Whereas if you insist on using V as Value, where does that leave the poor graph programmer who would like to use V as Vertex?

The assumption that _your_ domains and ranges should command single-char status is false and harmful.

Ken
 

Randall R Schulz

unread,
Nov 19, 2011, 8:07:57 PM11/19/11
to scala-...@googlegroups.com
On Saturday 19 November 2011, Kenneth McDonald wrote:
> I was assuming that the number of functions are known (or at least
> bounded), in which case the calculation is trivial.

I believe there are aleph_0 distinct discrete functions. Probably
aleph_1 distinct functions over continuous variables. Those are just
guesses, though...


> The observation was intended semiseriously...why represent _anything_
> with a number of characters greater than that necessary to guarantee
> a unique representation? Obviously, because further characters can
> add (for lack of a better term) meta-semantic meaning.

I did not detect the (implied) semi-humor. Sorry...

I don't know what "meta-semantic meaning" might be, but humans do
clearly benefit greatly from whatever connotative value they can derive
from the particular choice of symbols even though those symbols are, in
fact, entirely arbitrary.


> Ken


Randall Schulz

Kenneth McDonald

unread,
Nov 19, 2011, 8:20:38 PM11/19/11
to scala-...@googlegroups.com, Kenneth McDonald, tmo...@tmorris.net

Yes, because a very straight-forward and efficient answer is totally
off-the-charts.


As usual from you, you are spouting complete nonsense. If I were in such an interview, I would assume that my interviewer wanted to test my understanding of basic data structures. (Your assumption seems to be that the interviewer's expectations are spread out across the Milky way). I would then return an answer consonant with these expectations, and be willing to answer further questions on the same topic if the interviewer wanted.

Tony, don't you freakin' get it? You are brilliant (good) but virtually incapable of communicating with the rest of humanity who is below your level of brilliance. (This is bad. Don't ask me to go into why, if you don't understand it, even a brain transplant won't help). As long as you maintain your pretense of "superiority" over the rest of us, you will achieve almost nothing. If you come to understand that the rest of us do not do things the way you do and never will, then you have a chance to make a real contribution.

Just feedback from someone who would really like to read reasonable tract from you, but has never found one.

Ken

Kenneth McDonald

unread,
Nov 19, 2011, 8:29:38 PM11/19/11
to scala-...@googlegroups.com, tmo...@tmorris.net


On Thursday, November 17, 2011 11:03:01 PM UTC-6, Tony Morris wrote:
Type parameters are not just parameters like method parameters. The problem with projecting names onto type parameters, unlike method parameters, it that this departure from reality is *always* unwelcome (unlike coincidentally having no impact for method parameters). That is, you will always be wrong by virtue of them actually being universally quantified variables. You will never be right. There doesn't exist a case where projecting anything but "forall" onto a type parameter (in position of universal quantification) is sensible.


Ohmigosh Tony, don't you ever get tired of being wrong? If I specify a type Tree[Root, Branches], are the meaningfulness of those names somehow obviated by the faint possibility that my type (in the context of my library) might be used for something else? Of course not. For that matter, there's a faint possibility that my code with variable names might find an application where those variable names are meaningless. Who the ^(^*)% cares? Software is design for what is real, not what is might be. If you design for everything that might be, you never complete anything.

I used to think of you as brilliant, but the more posts I see, the more I think of you as simply irrelevant.

Ken

Kenneth McDonald

unread,
Nov 19, 2011, 8:31:06 PM11/19/11
to scala-...@googlegroups.com, Stefan Wagner


On Thursday, November 17, 2011 10:55:59 PM UTC-6, Josh Suereth wrote:

Guys,  it seems The utility of this discussion has declined.   Let's refrain from bloodying noses by continuing in the current vein.

I'll throw something out there.

Type parameters *are parameters *  just like method parameters.   If you think method parameters require a certain naming style, it is probably worthwhile to use this on type parameters.

If a type parameter looks like a class/type, that's similar to a method parameter looking like a member / term.   Notice the adjustments to the unofficial style guide for this.


Could you throw out a ref to the unofficial style guide?

Ken 

Tony Morris

unread,
Nov 19, 2011, 8:35:20 PM11/19/11
to scala-...@googlegroups.com

You crack me up mate.

Artem Khodyush

unread,
Nov 19, 2011, 8:37:50 PM11/19/11
to scala-...@googlegroups.com, Stefan Wagner
> Could you throw out a ref to the unofficial style guide?

It seems that most up-to-date lives now here: http://docs.scala-lang.org/style/

Tony Morris

unread,
Nov 19, 2011, 8:43:49 PM11/19/11
to scala-...@googlegroups.com, Kenneth McDonald

You've got to pull your head out of your rear-end if you'd like to have a chat. You know, clue up, come to terms with the fact that "you're just crazy" is not an acceptable argument, while lecturing others on communication skills. By the way, that looks really dumb y'know? Having no clue on the subject matter, vomiting incoherent arguments, proclaiming your victory all the while thinking you are somehow qualified to lecture on communication skills.

Let me know when you are ready to work toward a coherent and aspirational goal, whatever it might be; the subject matter at hand or not. I'm serious; until then, you have nothing interesting to offer. Don't take it personally. I lament harder than you do, promise.

Just let me know when.

Richard Wallace

unread,
Nov 19, 2011, 9:27:07 PM11/19/11
to scala-...@googlegroups.com, Kenneth McDonald, tmo...@tmorris.net
Ken,

The funniest - and saddest - thing in all of this is that Tony is
trying very hard to dissuade you of the opinion that he is so
brilliant!

When I started with FP a few years ago I felt the same as you do now.
It seemed complex. Guys like Tony seemed uber smart and I thought I
could never learn as much as they had. But then I started learning
the basic concepts, and the concepts that build on those, and so on.
I realized just how wrong I was. Tony is a smart dude, maybe smarter
than I am maybe not. But he's certainly been around the FP block
longer than I, and most other people, have been. So he's learned -
really learned, not just glossed over the concepts like some people do
- about FP and the concepts involved. As I've seen him say in various
other threads like this, it's not like he was born with this
knowledge.

You are hurting yourself - and I wish it was only yourself, but more
on that in a second - by continuing to say, "Tony is so much smarter
than me and everybody else, we can't possible ever understand all this
stuff. It's too complex!" In fact, it's not complex at all. It only
looks that way to someone new to the concepts, much like calculus,
linear algebra and differential equations look complex to someone just
learning basic algebra. But these are things that _everyone_ can come
to understand given time and effort.

If you don't want to put in the time and effort to learn these things,
then fine. But stop raising everyone who has taken the time and put
in the effort up on a pedestal - yes, you are the one putting them
there, they are not putting themselves there - and using that as an
excuse for you not understanding! You do them a disservice by saying
that's it is some natural born gift that allows them to understand
these things and - to retract what I said earlier - you perpetuate the
myth to others, causing them to be scared away by these concepts!
(When I was learning about monads the biggest thing I had to overcome
was all the hype around them. I understood the basics pretty quickly,
but thought I was missing something because of all the blogs and
people talking about how hard monads are to understand. But they are
the simplest things possible!)

So please, please stop with this, "It's so complex and your so smart I
can't possibly hope to understand this stuff the way you do,"
nonsense.

Artem Khodyush

unread,
Nov 19, 2011, 9:35:42 PM11/19/11
to Josh Suereth, Philippe Lhoste, scala-...@googlegroups.com
On Sat, Nov 19, 2011 at 10:33 AM, Josh Suereth <joshua....@gmail.com> wrote:

trait TypeFunctor {
  type F[x]
  def map[X, Y](f: X => Y): F[X] => F[Y]
}

> To those who don't understand the concepts of functors, these names are pretty poor.  However, if I *document* the concepts I'm using.

You don't have to understand the concepts of functors to see it, you just need to be familiar with some parts of Scala language - abstract types, type constructors, in-place function type definition with =>.

Then it's obvious that F is abstract type with one parameter, and map is a function that takes a function from X to Y and returns a function from F[X] to F[Y].

What is the best meaningful name for a type that all you know about is that it's an argument type of some unspecified function?  One-letter names seem appropriate here, as in lots of other similar contexts.

Your documented version seems actually worse to me - it repeats the same things over and over again, and obscures things by using category theory terminology (Don't get me started on category theory :)


>  If the variable has no meaning to be conveyed, then why is it in your source code?

Type-level source code is a little bit different. Unconstrained type variable is just a wildcard, if you take it to extreme it's just a de Brujin index - it's meaning is determined by the place it occupies in the expression, and nothing more. (but I digress again).


> Graph[N,V] may be poor, but Graph[NodeData,VertixData] doesn't seem poor to me at all.  Again, I can come up with a class Graph where these names make a *lot* of sense.

That one - Graph[NodeData, VertexData] indeed makes sense. Unlike all other graph examples, it's clear that NodeData and VertexData is just a payload attached to nodes and edges. 

Richard Wallace

unread,
Nov 19, 2011, 9:47:17 PM11/19/11
to Josh Suereth, Philippe Lhoste, scala-...@googlegroups.com

That's not really fair, is it? I would say that the most
disappointing library has to be the Scala standard library. When I
started using Scala I couldn't make heads or tails of anything. I had
to read books and blogs to understand what was useful to accomplish
the tasks at hand. There were and still are several places in the
scaladoc where concepts - some only known in the Scala community - are
used in a brief sentence describing a method, but no further
explanation is given. This is pretty piss poor for something at the
very core of the language.

Now I'm sure you and everybody else are getting ready to hit the reply
button to tell me all about the great strides that have been made in
documenting the standard lib. And I agree, it has gotten much better
lately. But that didn't happen until Typesafe was founded and the
focus of the Scala creators and maintainers shifted from making Scala
useful to getting Scala used.

Scalaz's creators and maintainers are currently more focused on making
something useful rather than something that is widely used. There is
a ton of documentation in Scalaz - it's all in the types! - and there
is voluminous amounts of pdfs and blogs about the underlying concepts.
No, that documentation has not been *copied* into the source code.
That has not been a focus. It is expected that people interested
enough in learning will Google the concept or ask on the mailing list.
But if you, or anyone else, wants to improve the situation submit a
pull request. As long as descriptions are accurate, they'll be
accepted.

Rich

Tony Morris

unread,
Nov 19, 2011, 10:05:06 PM11/19/11
to Richard Wallace, scala-...@googlegroups.com, Kenneth McDonald

So well put Richard.

The amount of damage that is done by perpetuating the myth that understanding the subject matter at hand is somehow unapproachable by speaking to all these logical fallacies is just sad. No I really want born with categorytheory.so in my brain our whatever nonsense it may require to continue justifying these myths (they astound me every time, so please excuse my naive guessing).

Fine, don't understand it, fine call me names, call me crazy or lacking communication skills, use all the fallacies at your disposal. I DO NOT GIVE A FUCK THAT YOU ARE WRONG AND I REFUSE TO TAKE YOUR BULLYING PERSONALLY.  But I do care that the next guy might fall for it. Thankfully Richard is not one of those and has taught me a few things on occasion and will likely continue to do so (thanks Richard).

To others, beware of the trap, especially the illusion of comfort it advertises. It's bullshit.

Russ Paielli

unread,
Nov 19, 2011, 10:36:41 PM11/19/11
to Tony Morris, Richard Wallace, scala-...@googlegroups.com
This question has no doubt been asked and answered a hundred times, but which online Scala FP or Scalaz tutorial do you recommend? I'm looking for something that is (1) freely available online, (2) starts more or less with the basics of FP and goes from there (3) provides examples in Scala. Thanks.

(Yes, I did a quick google on it, but the results do not appear to be particularly useful to me.)

--Russ P.
--
http://RussP.us

Eric Kolotyluk

unread,
Nov 20, 2011, 12:05:46 AM11/20/11
to scala-...@googlegroups.com
Applause!

Well said H[J,S] ;-)

Cheers, Eric

Paul Phillips

unread,
Nov 20, 2011, 1:02:48 AM11/20/11
to Richard Wallace, Josh Suereth, Philippe Lhoste, scala-...@googlegroups.com
On Sat, Nov 19, 2011 at 6:47 PM, Richard Wallace
<rwal...@thewallacepack.net> wrote:
> And I agree, it has gotten much better
> lately.  But that didn't happen until Typesafe was founded and the
> focus of the Scala creators and maintainers shifted from making Scala
> useful to getting Scala used.

Post hoc ergo propter hoc.

martin odersky

unread,
Nov 20, 2011, 4:15:29 AM11/20/11
to Tony Morris, Richard Wallace, scala-...@googlegroups.com, Kenneth McDonald
I can just say here: Sorry, Tony you are wrong. I think I am qualified to say that. I have been in FP much longer than you were. I am a member of the IFIP working group for functional programming, together with people like Peyton Jones, Wadler, Hughes. I am chairing the technical advisory board of Microsoft Research Cambridge which does both Haskell and F#. I am also a fellow of the ACM for my achievements in the area. 

What you do is the hard hard fringe of category theory, largely uninteresting even to the mainstream of FP.  Of course, over the years a number of papers and talks appeared on the subject; none of them got very far.

So, if you want to follow that side show (and a side show it is!) for personal pleasure that's great! But don't assume everybody else needs to follow you; don't even try to convince them. It's detrimental for them and for the success of FP as a whole.

 -- Martin


Tony Morris

unread,
Nov 20, 2011, 4:33:08 AM11/20/11
to martin odersky, Richard Wallace, scala-...@googlegroups.com, Kenneth McDonald

Martin, I have no idea what you think I am wrong about, but I am pretty
sure you are wrong about what it is I do and I am also pretty sure you
need to look at category theory a bit more so that you can better
understand it. No, I don't do the "hard hard fringe of category theory."
I have no idea where you even got that idea. Did you just make it up?

The credentials are unpersuasive.

--
Tony Morris
http://tmorris.net/


martin odersky

unread,
Nov 20, 2011, 4:50:49 AM11/20/11
to tmo...@tmorris.net, Richard Wallace, scala-...@googlegroups.com, Kenneth McDonald
I did not intend to convince you with this mail, Tony. I know you can't be convinced. I am trying to convince some of the others that what you say need not be taken as gold, because your position is fringe even in classical FP. I don't have the time like you do to monopolize discussions on scala lists with more than a dozen messages a day. So most likely I will not be able to respond in detail to future messages of yours. I trust you will not construe my silence as endorsement.

I think you would do the scalaz project and the community at large a great favor if you stopped posting on threads that are not directly related to scalaz.

 -- Martin 

Tony Morris

unread,
Nov 20, 2011, 4:57:40 AM11/20/11
to martin odersky, tmo...@tmorris.net, Richard Wallace, scala-...@googlegroups.com, Kenneth McDonald

I can be convinced of lots of things. I repeat, I was not born with my
current level of understanding and positions on various matters. I have
been convinced of various things to arrive where I am today. You've just
got to make sense in doing so. I am still not convinced that this is too
much to ask of the scala mailing list in general.

I was in the middle of a state forest on a dirt bike in outback
Australia when I responded to at least one of the messages. Time
management is not difficult.

Chris Twiner

unread,
Nov 20, 2011, 4:58:56 AM11/20/11
to Richard Wallace, Philippe Lhoste, scala-...@googlegroups.com, Josh Suereth

I want to "quickly" comment on the whole Scalaz documentation/complexity thing.

Disclaimer: I say this as an (ab)user of Scalaz.

Programming is hard, learning totally new concepts is hard - the payoff has to be worth the investment.  Documentation should provide enough of an overview to answer the "is it worth it" question.

Here Scalaz documentation is poor. It takes way too much time to be able to understand the why's and, perhaps more importantly the how's. The why's I will come back to, but the how's will be solved in large part by Scalaz 7.

7 makes a big shift in code organization, putting most type class instances right with their related type (not spread out over a few files). Scaladoc should then be a usable tool for discovering the how.

The why's on the other hand require a bit of searching - see the deriving presentations and read those scary Runar blog posts, hell you can even read about Elephants if it helps. I believe that the upcoming book might provide the overview that most need.

The important part is this: you will reinvent parts of Scalaz sooner or later. Key parts of your existing code base already do.  Personally I have reinvented:

* Equal
* Validation (badly I might add)
* Iteratees
* Ephemeral stream
* Tree based zippers (although my implementation better fits my needs)

I was for a time also on the verge of reinventing arrows.

Any perceived complexity in Scalaz is due to how general it is and how hard it works around and within the type system to give you those goodies.

I write all this because these last few posts from Ken keep coming back to Scalaz, of course with some help from the ever communactive Tony.

It's a distraction - Scalaz is generally useful, and if you find yourself asking "this fp style thing seems it should be reusable" then look in Scalaz.  If it's not obviously there ask in the Scalaz group, perhaps looking at it slightly differently makes all the difference.

To finish: I personally find it very comforting that, in Scalaz, there is a library that provides a one stop shop for solving many of my abstraction issues. I don't buy into "follow the types" you *do* need easier intros to get going (the internet is full of them) but the payoff *is* worth it - promise. (sorry Tony couldn't resist)

Tony Morris

unread,
Nov 20, 2011, 5:03:25 AM11/20/11
to scala-...@googlegroups.com

You're not the first person to accidentally reinvent many concepts in
scalaz. Even Martin did exactly that a couple of weeks ago.

I appreciate your honesty. It should probably go on the scalaz mailing
list though. No need to apologise.

martin odersky

unread,
Nov 20, 2011, 5:52:36 AM11/20/11
to tmo...@tmorris.net, scala-...@googlegroups.com
Of course these are useful concepts in scalaz! But the approach that you have to understand it in its entirety is wrong, IMO. And I believe few of the scalaz maintainers would claim that you need to. Also, sometimes it's more enlightening if you _do_ rediscover some of these features yourself than if you are made to swallow the whole tower of abstraction at one go. Makes you more appreciate their usefulness.

A criticism of category theory, which I share, is not that it does not present useful concepts. In a sense category theory is the most general of all theories so of course it will describe a lot of useful concepts. The criticism is that the concepts covered by category theory tend to be very general but are often not very deep*, and the overhead of learning category theory is not paid back by the usefulness of applying it. That's why category theory did not make greater inroads into mathematics and computer science (it was quite fashionable in both branches for a while, at different periods in time).

* By deep, I mean: the _application_ of the concept in a concrete scenario would otherwise require a hard proof (if we talk about mathematics) or very involved code (if we talk about computing).

My favorite here is the Richard Feynman auto-biography, where he talks about Brasilian physics education of the 60s. That education was very abstract and deductive. It presented a bunch of laws which students had to memorize, but could not apply to anything real. Feynman was very critical of this approach, of course. 

So, I believe if scalaz should have wider appeal to people, it will need to stress self-discovery more. Instead of just pushing a library out, develop material how people can discover central abstractions themselves. Another great example how that's done is Structure and Interpretation of Computer Programming by Abelson and Sussman.

Cheers

 -- Martin

Tony Morris

unread,
Nov 20, 2011, 5:59:30 AM11/20/11
to martin odersky, tmo...@tmorris.net, scala-...@googlegroups.com

Martin,
How do you propose we get people to knowingly discover concepts (in
contrast to unknowingly discover, as they currently do), when you have
seen the general attitude to learning these things? It's much tougher
than you might imagine -- indeed, look at the roundabout we went on
before you discovered that you'd invented "the essence of the iterator
pattern" in a previous thread. What about others?

You regularly ask me why I bother with this mailing list -- now I can
answer. It's because occasionally someone will contact me, in private or
something, who has had a genuine insight and is looking for discovery.
It's cheap for me when that happens because all I need to do is give the
appropriate leads and that person(s) goes off to discover for
themselves. Like I said, time management is not difficult and I will
pick off the easy fruit on this mailing list -- this includes putting up
strong resistance to the anti-think squad, which is important to others'
learning.

PS: You really need to let go of the category theory thing. It is
absolutely not representative of what we are discussing.

martin odersky

unread,
Nov 20, 2011, 6:07:58 AM11/20/11
to tmo...@tmorris.net, scala-...@googlegroups.com
The fact that you describe them as the anti-think squad is insulting. They choose not to specialize in your area. They have other problems to worry about. Just let them do that instead of calling them names.

 -- Martin

It is loading more messages.
0 new messages