Live data from Hacker News

Haskell in the Large [pdf]

code.haskell.org

81–90 of 139 posts

Re: Haskell in the Large [pdf]

#81
post #51
post #29

Earlier quoted context omitted.

Strictness can always embed laziness---this is sometimes an argument for the natural superiority of strictness---so long as you have lightweight lambdas. Thus, in OCaml you'll see a lot of thunk () = long_computation effectively. Is that syntactic noise enough to disable the advantages of laziness? Actually, maybe!

> Strictness can always embed laziness And vice versa, although I think embedding strictness in laziness is probably more syntactically heavyweight. http://h2.jaguarpaw.co.uk/posts/strictness-in-types/ > Is that syntactic noise enough to disable the advantages of laziness? Actually, maybe! Hmm, if that's the case then it seems that thunk = return long_computation is enough to disable the advantages of monads! :)

And w.r.t. to monads, for a lot of people it is! Most use of monads is done implicitly, right? ;) The only reason Haskellers tolerate the extra syntax is because it's statically required (I claim).

There's an advantage here, of course, in statically ensuring that people do something more explicitly than they would like to. Perhaps the same advantage applies to thunking.

Honestly, I'd rather not comment. I don't know that I or nearly anyone has enough information to make strong, confident opinions about the "right way" to do lazy/strict. I'm hoping that the research into total languages will provide answers!

Re: Haskell in the Large [pdf]

#82

Earlier quoted context omitted.

So if I understand correctly, the real point is instead of programming defensively at runtime, you can do it in the type system. My main question is the extent to which this is possible in more conventional languages.

Yep - that's probably a fair way to describe it. It's of course possible in other statically typed languages, it's just not as easy. There are also some things that I'm not sure are reasonable at all in something like Java/C++ without writing a lot of code. For example: https://www.chrisstucchio.com/blog/2014/type_safe_vector_add...

Thanks for the link. I've been wondering how to lift N-D operations into the type system. If I write with NumPy

  x = r_[:n].reshape((3, -1, n/15))[:, :2].sum(axis=-1)
a compiler could figure out that the shape of x is (3, 2) and allow

  y = x + randn(m, 1, 2)
while forbidding

  z = y - r_[:7]
With NumPy you have to wait for a runtime error, and only if the shapes can't be broadcast. We're not even talking correct use of dimensions, etc.

I suppose this may have been tackled in Haskell in the Repa library, but I'd need to read papers like

http://benl.ouroborus.net/papers/repa/repa-icfp2010.pdf

to know. Hence my question if we could lift this into the type system in a conventional language, but I don't think it's possible in a general way.

Re: Haskell in the Large [pdf]

#83
post #75

Earlier quoted context omitted.

So if I understand correctly, the real point is instead of programming defensively at runtime, you can do it in the type system. My main question is the extent to which this is possible in more conventional languages.

Just imagine that every static constraint you want to encode has to be written in the language of the types, a subset of your chosen language. C's language of types is incredibly primitive. Haskell's is quite nice. Agda/Idris/Coq's type language is technically equivalent to its value language so you can encode incredible things. It turns out that due to people's general desire for compilation to always terminate that…

Would you then accept a worthless value language if the type language was perfect?

Anyway, this was quite an enlightening comment for me: Agda/Idris/Coq's type language is technically equivalent to its value language.

Given a sufficiently interesting type language, could we statically type the problem I posed in another comment here

https://news.ycombinator.com/item?id=8966065

?

Re: Haskell in the Large [pdf]

#84
post #45

I'm really happy to hear about Standard Chartered's success with this, and I want to know more. This is really promising stuff. My current company is looking into our "next generation" platform for when our datasets exceed what we can do in R. R may not be the best language, but it's great for exploratory data science, has the best or the only library out there for some ML purposes, and we've done a lot of things to…

Not something I've used myself yet, but is there any particular reason Julia isn't on that list?

I haven't checked on Julia for like a year, but back then Julia didn't offer anything above and beyond R when it comes to "big" (really just not fitting into memory) data. As it is Spark with Scala is both faster and more convenient than R or Julia.

Re: Haskell in the Large [pdf]

#85
post #75

Earlier quoted context omitted.

Just imagine that every static constraint you want to encode has to be written in the language of the types, a subset of your chosen language. C's language of types is incredibly primitive. Haskell's is quite nice. Agda/Idris/Coq's type language is technically equivalent to its value language so you can encode incredible things. It turns out that due to people's general desire for compilation to always terminate that…

Would you then accept a worthless value language if the type language was perfect? Anyway, this was quite an enlightening comment for me: Agda/Idris/Coq's type language is technically equivalent to its value language . Given a sufficiently interesting type language, could we statically type the problem I posed in another comment here https://news.ycombinator.com/item?id=8966065 ?

I'm not sure anyone has developed a language with a great type level language and a worthless value level one. But that said, theorem provers (like Coq) essentially consider value-level computation as vestigial: nobody cares about running Coq programs, just checking them.

To encode what you're looking for requires type-level natural numbers and a reasonable notion of type-level equality. These are fairly non-trivial. You can encode this in Haskell, but type leve" equality is a bit hard to work with so you may suffer some pains (I know, I've done it several times!). Agfa and Idris would be where I would look to see this sort of thing materialize.

Re: Haskell in the Large [pdf]

#86
post #77

Earlier quoted context omitted.

First, people are not shy about using short names in general, however polymorphic the variable is. And you could easily write: map func (item:items)

The point is typically something like "generic english names don't provide much benefit over conventional short names". When I'm writing map, parametricity literally ensures that I cannot care about the element of the list. Giving their priority with any thought toward the name is actually taking the focus off the list structure where it belongs.

That's nice, but when reading non-trivial code, having "generic English names" makes the programmer's intention easier to decipher than a random sprinkling of 5 different one-letter variables - though it's fine to have ecosystem-wide conventions for the most common cases.

Re: Haskell in the Large [pdf]

#87
post #78
post #55

Earlier quoted context omitted.

The modules are great in OCaml. The short variable names in Haskell follow the convention that the more polymorphic your variable is, the shorter its name should be. Eg in map f (x:xs) = f x : xs; map _ [] = [] f, x and xs are very polymorphic, so there's really no better longer name there.

map fn (head:tail) = (fn head):(map fn tail) map _ [] = []

Your version, while not very different, is not easier to read than that of the parent post.

A few weeks into learning Haskell, reading x:xs will become second nature, so much so that "head" and "tail" become noise. (Also, "head" and "tail" are function names in the Prelude, but I'll assume you meant to write "hd" and "tl" or something like that).

Re: Haskell in the Large [pdf]

#88
post #84
post #45

Earlier quoted context omitted.

Not something I've used myself yet, but is there any particular reason Julia isn't on that list?

I haven't checked on Julia for like a year, but back then Julia didn't offer anything above and beyond R when it comes to "big" (really just not fitting into memory) data. As it is Spark with Scala is both faster and more convenient than R or Julia.

Spark has a python API and python has a bigger ecosystem for exploratory data analysis than spark.

Also python has a big data interface with out of core matrices and tables as well as a compiler than can speed numerical code, with a just a function decorator, to C like speeds. The former is an interface to the latter.

http://blaze.pydata.org/docs/dev/index.html https://github.com/numba/numba

Re: Haskell in the Large [pdf]

#89
post #4

I wonder what's the primary reason for their "Mu" compiler adopting a "strict-ish" evaluation strategy.

I don't know, but in my limited experience, lazy evaluation makes memory use worse (usually not much), but more importantly makes performance (time and memory) harder to reason about, because you don't easily know when something will actually evaluate. Besides that, there's also not much practical gain from it, IMO. One commonly cited benefit is a function that doesn't use all of it's arguments, therefore saving comp…

> But realistically, an unused parameter should probably be removed.

Think about the function if-then-else, which you may be familiar with from your favorite language :)

    if-then-else true branch1 branch2 = branch1
    if-then-else false branch1 branch2 = branch2
Obviously you don't want both branches evaluated in any given invocation, and obviously you cannot remove the unused parameter. Note that the purpose is not to "save computation", since for example branch1 may be undefined if cond is false!

When using a language with support for lazy evaluation, you encounter this kind of functions all the time.

Re: Haskell in the Large [pdf]

#90
post #77

Earlier quoted context omitted.

The point is typically something like "generic english names don't provide much benefit over conventional short names". When I'm writing map, parametricity literally ensures that I cannot care about the element of the list. Giving their priority with any thought toward the name is actually taking the focus off the list structure where it belongs.

That's nice, but when reading non-trivial code, having "generic English names" makes the programmer's intention easier to decipher than a random sprinkling of 5 different one-letter variables - though it's fine to have ecosystem-wide conventions for the most common cases.

I would argue that in non-trivial code when variables represent meaningful concepts it is Haskell tradition to use long, descriptive variable names. Sometimes these are even longer than in other languages since that's a tool used so rarely.

The trick is that once you're exposed to short names at the right places you realize that there are relatively few times that variables are meaningful as much more than function-wiring notation. Especially in pure code!

As soon as you add in mutability this all goes out the window really fast. Subsequently, you see "meaningful" variable names all the time in IO or ST code.

Post reply on HN