News for hackers. Stuff that matters.
Re:Making the move from Scala to Go by imh on Tuesday January 24, 2017 @09:49PM (#13478025)
Looking through the really abstract scala code they linked brings up a problem that really frustrates me in haskell. Why doesn't anybody document their really abstract code? You know it's going to be confusing, so why not help out? If I have a type like

    def foreignKey[P, PU, TT <: AbstractTable[_], U] ...
It's not sufficient to document the function's arguments. You also need to document the type variables! Likewise in haskell with code like

    f . g x . (h (i x) $ j y z) . k $ aNamedVariable
It really isnt' so hard to refactor that into

    let descriptivelyNamedFunction = (h (i x) $ j y z)
        anotherDescriptivelyNamedVariable = descriptivelyNamedFunction . k $ aNamedVariable
     in f . g x $ anotherDescriptivelyNamedVariable
It's much larger, but in certain places it prevents so many headaches. It's great that you can put stuff inline, but both communities seem super lax about accepting code that is the opposite of self-documenting.

edited for clarity, i hope

Re:Making the move from Scala to Go by tel on Wednesday January 25, 2017 @01:41AM (#13479252)
I mostly agree with you, but I also think a bit part of what Haskell-like FP shows is how often your code is invariant to so many things that the variables no longer have any sense to them whatsoever.

That doesn't really excuse badly named variables when that doesn't hold. It's more that it's something sort of novel to a lot of Haskell-like programmers and so we all get excited about it and probably overdo it somewhat. But on the other hand, I think it's very well-justified often enough.

For instance, with

    class Functor f where
      fmap :: (a -> b) -> (f a -> f b)
there are many words you could give to f, a, and b but they're essentially all misleading.

With another example from the article, Strong Syntax, the "Syntax" bit is basically a convention in scalaz that ought to be immediately obvious if you're familiar with the scalaz library. The "Strong" bit has to do with a subtype of "Profunctor" structures, "Strong Profunctors".

Profunctors are generalizations of functions that show up all over the place. Strong profunctors are profunctors which can "distribute over a tuple".

Giving names to these types is an exercise in futility. At least with a function `a -> b` might be named `in -> out`, but with a Profunctor there isn't even that intuition. It's just too general. Subsequently, it shows up all over the place.

Re:Making the move from Scala to Go by aninhumer on Wednesday January 25, 2017 @04:44AM (#13480063)
> At least with a function `a -> b` might be named `in -> out`, but with a Profunctor there isn't even that intuition.

What about:

  dimap :: (newIn -> in) -> (out -> newOut) -> p in out -> p newIn newOut
Re:Making the move from Scala to Go by tel on Wednesday January 25, 2017 @08:27AM (#13481191)
With profunctors there's not necessarily anything going in or out and especially not necessarily and notion that the thing going in produces a thing going out.

That's all roughly true with one kind of profunctor, a function arrow, but not true in general.

For instance,

    data Counterexample a b = Cx (Set a) b
is (very, very, very nearly [0]) a profunctor, but a isn't necessarily "going in" and b isn't necesssarily "coming out".

[0] It's a profunctor if a is finite. You can handle the infinite form by writing it as `data Cx a b = Cx (a -> Bool) b` which is equivalent to what I wrote when `a` is finite... but it also makes it a little easier to pretend that a is "going in" even if that's a bad intuition.

Re:Making the move from Scala to Go by aninhumer on Wednesday January 25, 2017 @10:24AM (#13482096)
I'm not sure I see how the intuition is bad here? What would the lmap implementation for your (Set a) example be if not equivalent to the (a -> Bool) case? And how is that not an example of data "going in"?

More generally even if there are Profunctors for which this analogy isn't perfect, I feel like the intuitive type names are still more useful than random letters. Especially for a relatively advanced concept like Profunctors, for which I expect pretty much all users to be comfortable with the idea that a type variable does not necessarily imply that concrete values of that type will exist.

Re:Making the move from Scala to Go by tel on Wednesday January 25, 2017 @02:08PM (#13484801)
It is equivalent to the (a -> Bool) case. In Haskell at least, all "negative type parameters" are ultimately generated by the left side of a function—but this is more a concern for how ideas are modeled (perhaps partially) in Haskell then a fundamental one. If you're writing code that's

    forall p . Profunctor p => ...
then `in` and `out` aren't generally valid.

I definitely hear the argument that ergonomically it might be a good idea to use a sort-of-appropriate model to drive better terminology... but at the same time I think there are drawbacks. I think it helps the early part of a learning curve but then hinders the latter part. An expert doesn't care what they're called since they're just mentally erasing the names as appropriate anyway. A non-expert will try to carry the metaphor further than it can go and gets stuck.

This is why there's endless debate about calling Monoid "Appendable" or something like that. For the commonest cases that's the right idea... but the first time someone questions why there's an Appendable instance for Bool (two, actually!) you're fighting with your own inappropriate metaphor.

"Oh, Appendable actually means Monoid but we didn't want to say that straight up."

Re:Making the move from Scala to Go by flukus on Tuesday January 24, 2017 @10:39PM (#13478254)
Would descriptive types help?:

    def foreignKey[PNamedType, PUNamedOtherType, TTlongTypeDescription <: AbstractTable[_], U] ...
I know they help a lot in c#.
Re:Making the move from Scala to Go by fspear on Wednesday January 25, 2017 @12:09AM (#13478725)
This is what I really hate about functional programming (specially Haskell), is almost as if the more obscure and unreadable your code is the more competent you are deemed to be.
Re:Making the move from Scala to Go by brangalina4eva on Wednesday January 25, 2017 @07:16AM (#13480779)
It's like someone's run code through an obfuscator before committing.
Re:Making the move from Scala to Go by runT1ME on Tuesday January 24, 2017 @09:54PM (#13478048)
What do you mean "document the types". They're type parameters... can you suggest better names for the parameters in StrongSyntax?
Re:Making the move from Scala to Go by imh on Tuesday January 24, 2017 @10:19PM (#13478170)
As a small example, let's say I have a typed "agg" function with associated typeclass:

    class typedAgg t where 
      agg :: t f r a b -> (r a -> b) -> f (r a) -> f b
      ...
To lots of people, that's going to be really confusing. It might be easier if I document that f is supposed to be the type of the table, r is the type of the row, and a is the type of elements in the rows, if that's the intended usage.
Re:Making the move from Scala to Go by runT1ME on Tuesday January 24, 2017 @10:26PM (#13478208)
But I'm saying, if you have a Higher Kinded Type like Strong, what do you name the variables? They don't refer to actual nouns. We're abstracted from that level.
Re:Making the move from Scala to Go by imh on Tuesday January 24, 2017 @10:31PM (#13478222)
In my example, t, f and r are HKTs. Does that clear up what I mean at all? Strictly speaking in my example, f (r a) is the type of the table, but it's still illustrative to say that f is the type of the table, or say that it's probably a functor or at least similar to one.

Specifically with Strong, I'm not sure what I'd comment, as I'm not that comfortable in Scala yet and don't know what Strong is. I'm not going to go digging around and there are basically no comments in that file, which is the problem I'm talking about.