Live data from Hacker News

Three Months of Go from a Haskeller’s perspective (2016)

memo.barrucadu.co.uk

151–160 of 162 posts

Re: Three Months of Go from a Haskeller’s perspective (2016)

#151
post #106

Earlier quoted context omitted.

> However, that doesn’t necessarily imply an all-or-nothing approach where either you’re in a pure function or you can do anything with anything. To elaborate this point I'd say that the most important practical use of all that "monad mumbo-jumbo" in Haskell is that you can tag your functions with what they can and can't do and then the type system tracks this for you: -- pure function f1 :: Text -> Int -- can fail f…

The trick seems to be how to implement this kind of idea in a composable way, so we can still have a clear, modular design and write generic, reusable code even in the presence of several different types of effect. IMHO, the research into type and effect systems in recent years has been promising, but also shows that this is not an easy problem to solve. I’m hoping that in a few more years we might see a new generati…

Unison's ability system (an implementation of algebraic effects) is looking promising as an ergonomic method of tracking effects.

Re: Three Months of Go from a Haskeller’s perspective (2016)

#152

Earlier quoted context omitted.

Definitely! I couldn't get my head around why people like untyped languages, but I keep an open mind on it. I won't close off that they could be better, if the right patterns/practices are used (whatever they are!)

I joked with a friend that as people get older they start to prefer static typing. I personally don't have a preference, it depends on the application. I think it's obvious what are the advantages of static typing so let me rant about what is for me the main disadvantage: as soon as you have an advanced type system people will try to get creative writing code in the most abstract possible way. It's inevitable. It's t…

I agree and disagree. I love how you can do abstraction in Haskell based on the minimal interface. If it's "ring-like" or whatever you can define matrix multiplication. That can often come up useful, extending the power of existing functions.

But it means your web scraping code, crud app, {some other boring everyday app} or whatever is now adorned with all this deep mathematical complexity that if you just used nodejs or something it would be easier to understand.

Premature optimization is probably a good term for it, because the good think about haskell is it is easy to make refactoring. Make things specific now and more general later, and it should be backwards compatible for the most part.

But making things into "arrows" is part of the sport I think.

Re: Three Months of Go from a Haskeller’s perspective (2016)

#153

Earlier quoted context omitted.

Go is incredibly readable I find. Yes, you tend to find yourself writing a lot of code because of the lack of generics, but that is being fixed as we speak. Generics has a draft and it looks nice from a Go developers perspective. And Go let's you communicate by copying. That's what a Channel is. Pass a struct and that is copied. Pass a pointer and the pointer is copied. The thing it points to isn't copied for glaring…

> And Go let's you communicate by copying. That's what a Channel is. Pass a struct and that is copied. Pass a pointer and the pointer is copied. The thing it points to isn't copied for glaringly obvious reasons. Copying large structs is not ideal, but passing a pointer to the channel means the other side of the channel can mutate that data. If Go had immutable types, you could pass a constant pointer, allowing the ot…

> What he's talking about is returning a union type. You have a single return value, it's type is either a valid result (i.e. a string) or an error. The compiler expects you to do runtime type checks (basically) to assert whether your return value is actually a value or not.

Not quite. I am suggesting a tagged union. Not a runtime type check.

You'd check the tag.

Some language only support the runtime type-checked version of union types. That's a bit silly. For example, it makes it much harder to write a function that may either error out itself, or produce an error message as its bona fide value.

Re: Three Months of Go from a Haskeller’s perspective (2016)

#154

Earlier quoted context omitted.

Regarding the example in your first point, you are still sending a reference `m` of the map. If you wanted to send an immutable type, you could declare the channel to only accept struct values (and not pointers to structs) and you'll get your desired behavior. Here's a playground for reference: https://play.golang.org/p/U2tYZVTtUf-

Given that there is no way to make a non-pointer map in Go, there is no workaround for the example they gave. The broader point is that there is no way in Go to ensure that data passed over a channel will not be modified concurrently without modifying the type of the data specifically for the channel use case. A deep_copy() primitive would fix this.

Yes, either a deep_copy() or a way to declare things immutable. (Or both.)

Re: Three Months of Go from a Haskeller’s perspective (2016)

#155

Earlier quoted context omitted.

Given that there is no way to make a non-pointer map in Go, there is no workaround for the example they gave. The broader point is that there is no way in Go to ensure that data passed over a channel will not be modified concurrently without modifying the type of the data specifically for the channel use case. A deep_copy() primitive would fix this.

Right, but they mentioned sending immutable structs which is why I gave the struct example. But you're right that every declared map is a just a pointer. With respect to your second point, I see what you mean but I still don't think that's a negative of Go. You can pass in copied values without having to have a deep_copy() primitive (loop map values and copy to new map, dereferencing a pointer, etc.). Like other part…

You'd have to roll your own deep_copy by hand (or code generation) for every single data type.

Re: Three Months of Go from a Haskeller’s perspective (2016)

#156

Earlier quoted context omitted.

Go is incredibly readable I find. Yes, you tend to find yourself writing a lot of code because of the lack of generics, but that is being fixed as we speak. Generics has a draft and it looks nice from a Go developers perspective. And Go let's you communicate by copying. That's what a Channel is. Pass a struct and that is copied. Pass a pointer and the pointer is copied. The thing it points to isn't copied for glaring…

I think even more than the lack of generics, Go is difficult to read because it forces you to mix the error path with the success path in every function which can possibly fail, often making you bubble errors up the call stack manually.

Well, the onerous error handling is a symptom of the lack of generics.

Go has no facilities to would allow you to abstract away the repetitive parts of error handling.

Re: Three Months of Go from a Haskeller’s perspective (2016)

#157
post #135

Earlier quoted context omitted.

I get your point, but if we're all bad then "bad" loses its meaning. I'm definitely a better programmer than many of my peers, and worse than a whole bunch of others.

We're bad, not in comparison with each other, but in comparison to the external standard of "good enough that we don't need a crutch". In fact, if you want to be a better (less bad) programmer, learn to use the available crutches more effectively.

Well, it's a bit like saying that computers of the electronic kind are a crutch for bad computers of the human kind.

Or that planes are a crutch for bad travelers who can't fly under their own power.

Re: Three Months of Go from a Haskeller’s perspective (2016)

#158

Earlier quoted context omitted.

> I couldn't get my head around why people like untyped languages What do you mean exactly with "liking" untyped languages? I personally program mainly in both a ("cognitively demanding") typed and an untyped languages, and they have different use cases. For relatively small programs, untyped languages are much faster to develop. A program I wrote yesterday in a few hours would have taken 2 to 4 times as much in a ty…

Is that true? A simple program that isn't going to see long term use means I don't have to worry about anything but the happy path, either typed or untyped. And something where I have to nail down the edge cases is easier in a typed language.

True? I personally have no doubt (of course, programs vary a lot, so there are certainly cases where the effort is comparable).

Besides the unstructured trees, another example, although more high-level, is interfaces. They're a concept required in statically typed languages (some languages they have a simpler design than others), but not in dynamically typed languages (which have duck typing).

If you have a couple of types that you need to abstract, in a S.T. you'll need to define an interface, the method signatures, which include the return types, and maybe (in lower level languages) the generic types and the super interfaces. Even something as (relatively) simple as generalizing a tuple and a matrix types will require some design.

In D.T. languages, zero effort is required. As long as an object responds to a method (name), it's game.

I think it's not realistic to assume that the concepts that need to be taken care of in a S.T. language are comparable to the ones in a D.T. language. And more concepts imply more cognitive load. And cognitive resources are limited :-)

Re: Three Months of Go from a Haskeller’s perspective (2016)

#159
post #106

Earlier quoted context omitted.

> However, that doesn’t necessarily imply an all-or-nothing approach where either you’re in a pure function or you can do anything with anything. To elaborate this point I'd say that the most important practical use of all that "monad mumbo-jumbo" in Haskell is that you can tag your functions with what they can and can't do and then the type system tracks this for you: -- pure function f1 :: Text -> Int -- can fail f…

The trick seems to be how to implement this kind of idea in a composable way, so we can still have a clear, modular design and write generic, reusable code even in the presence of several different types of effect. IMHO, the research into type and effect systems in recent years has been promising, but also shows that this is not an easy problem to solve. I’m hoping that in a few more years we might see a new generati…

I haven't yet looked much into effect systems so can't really talk about them but I think even with something like MTL you can achieve a decent level composability/modularity where you build up a library of capabilities that you can then use to pick and choose effects from, eg.:

  type FooContext m = (GetTime m, GenUUID m, Log m, Auth m, ReadDB m, WriteS3 m, BarApi m, etc...)

  foo :: (FooContext m) => UUID -> m Foo
The main downside is ergonomics, ie. the amount of boilerplate needed, but personally I don't think that's a high price to pay.

Re: Three Months of Go from a Haskeller’s perspective (2016)

#160
post #86
post #67

Earlier quoted context omitted.

Prototyping or gluing components together is definitely faster without static typing.

I think this is a fault of language ergonomics rather than static typing. If you are gluing components together, then surely the components have a common interface that uses compatible types. And surely you need to tell the runtime what those types are in some way, even if that is simply by writing them to return appropriate values. In theory, a statically typed language with ideal ergonomics would make that as easy…

In my experience when gluing things one needs at the very least dependent types to properly express relations. Without that the best hope is a good integration test, but with that in place static types for things that can be expressed in mainstream languages do not bring much extra value while contributing to the cost.
Post reply on HN