Live data from Hacker News

Lisp and Haskell (2015)

markkarpov.com

121–130 of 173 posts

Re: Lisp and Haskell (2015)

#121
post #73

Earlier quoted context omitted.

I'm not sure what "Haskell developers" are saying, but this Haskell developer says "Haskell provides many tools that can be used to solve programming woes. One such tool is its strong and flexible types system (there are several other tools, such as immutability, functional style)."

And Python provides readable syntax . Your example has an easy-to-spot bug, just from reading the code and knowing Python's semantics. Haskell's "programmable semicolon" ends up being a problem here because, thanks to typeclasses, the programmer usually does not know which semicolon they are programming under! "Python provides many tools that can be used to solve programming woes. One such tool is its strong and read…

The problem with this comparison is that readable syntax is a subjective notion, whereas type system is an objective thing that can be evaluated based on its strictly defined boundaries - it's either possible or impossible to encode all required software specification with a provided type system, and if something is not possible, we know exactly what are these things that don't fit into the type system, and therefore we cannot rely on the compiler to prove their correctness.

Re: Lisp and Haskell (2015)

#122
post #39

In Clojure it's common to develop your application by building it inside a running system Every REPL form sent recompiles the running program, I don't want that fast loop to be force lagged by the program checking types I'm more than happy for that to happen at edit time, independent of compile time outside of my application process So I heavily encourage using clj-kondo to check for mistakes doing primitive type che…

I hear this "code as system is running" a lot. Doesn't it complicate our reasoning about the program as compared to simple text files? I haven't heard the other side of this claim.

You still have the simple text files, but while you're developing (and perhaps in exceptional circumstances while it's running) you interact with it in a live fashion. But the source code is still there, and the whole thing can be recreated from scratch if you kill the image by loading the code.

This lets you do things like (stupid trivial example follows, Common Lisp not Clojure) write a function from inside out in the REPL, then move the code to source:

  > (+ 1 2)
    3
  > (let ((x 1))
      (+ x 2))
    3
  (defun add-two (x) ;; in a source file
    (+ x 2))
  > (add-two 1) ;; after evaluating/compiling the above
    3
Imagine that these were more complicated things, like you're using a web API and getting JSON files and parsing them. You can develop it interactively, and as you verify that things are correct, you can migrate them to functions (and add tests to really do the verification part).

Re: Lisp and Haskell (2015)

#123
post #31

Earlier quoted context omitted.

I find these generally worth it because you can surface those aspects up to the function signature. It would be a lot nicer to have a function signature that shows the limits than it is to have a failure and have to open the docs for the library to see what the limits are. If the code is sound, it should have the same complexity anyways. I.e. putting a non-empty requirement in the function signature is just as comple…

I used to think Javascript was a great prototyping language. In fact I specifically practiced prototyping with it -- my github is littered with repo's for each of my prototypes -- I call them the Laundromat Demos. I would use the 70-80 minutes I had at the laundromat to write a prototype for a game in JS. However I've tried something similar with Haskell. I think I prefer Haskell for prototyping these days. It turns…

Interesting correspondence between your comment and sfvisser's:

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

Re: Lisp and Haskell (2015)

#124
post #101

Earlier quoted context omitted.

Difficult to explain cause not an expert, but most languages do not have "list comprehension" by post-description. "New York has rats bigger than a dog" comes to mind. In Finnish you can but the adjective word have same ending or grammatical case as the main word. Without those clues the sentence would be nonsensical.

> but most languages do not have "list comprehension" by post-description. "New York has rats bigger than a dog" comes to mind. « New-York a des rats plus gros que des chiens »

That is an indo-european language. Those languages have no grammar or rules. You just string words together and hope it makes sense.

Re: Lisp and Haskell (2015)

#125
post #59
post #23

I played around with Hackett (a parenthesised Haskell) quite a lot, and I really enjoyed creating my own syntactic abstractions in a haskell-like language. I find I would rarely reach for macros in Haskell, but that I sometimes would like to. Lisp macros do overlap with what you can achieve with Haskell things like typeclasses, laziness, monads and template Haskell, but the overlap is far from 100%. The author of Hac…

Hackett would be pretty much the argument for me to choose Racket - but the development is dead at this point.

Racket platform dev itself dead, or Racket program dev dead? As for the former, I'm on the email distro and it seems pretty active to me.

Re: Lisp and Haskell (2015)

#126
post #59

Earlier quoted context omitted.

Hackett would be pretty much the argument for me to choose Racket - but the development is dead at this point.

Racket platform dev itself dead, or Racket program dev dead? As for the former, I'm on the email distro and it seems pretty active to me.

There's an issue on the Hackett Github page where the dev says he doesn't have any free time to keep developing it. That's where I got it from.

Re: Lisp and Haskell (2015)

#127
post #12
post #5

> if your code compiles, it probably works I'm always a little frustrated whenever I see this aphorism perpetuated since I think it gives the impression that a static type system is doing more than it is actually doing. In type systems that are used outside of academia, the main thing your static types are doing is checking whether the shapes of your data and functions all line up. With some small exceptions, that's…

Type systems can encode proofs of properties that you want your data to have. For example, suppose you want to write a function that returns the first element of a list. head :: [a] -> a This is the type of a function "head" that takes a list of values of some arbitrary type a, and returns an a. if you feed this function an empty list, what will it do? You can reason from the type signature that the only thing it pos…

Shouldn't head return "Maybe a", since the head of an empty list would be "None"? (Not sure if I got the Haskell terminology correct.)

Re: Lisp and Haskell (2015)

#128
post #119
post #64

Earlier quoted context omitted.

The Foldable instance for Maybe is one of the biggest warts in Haskell. It's not limited to Haskell, by the way. def getUsers(f): return (logged_in_users(f), logged_out_users(f)) def userCount(f): return len(getUsers(f))

To make this code clearer: def get_users(f) -> Tuple[List, List]: return (logged_in_users(f), logged_out_users(f)) def user_count(f) -> int: return len(get_users()) Now it's clear this is just wrong code. To fix it: def get_users(f) -> List: return logged_in_users(f) + logged_out_users(f) def user_count(f) -> int: return len(get_users())

That doesn't really "fix it". Even assuming there are no other callers of `get_users` that you might be breaking here (possibly silently, since lists and tuples in Python have overlapping interfaces), you're making `get_users` less useful by dropping structure that at least someone, at some point, thought was useful.

Also, you should annotate the type of your lists :)

  def get_users(f) -> Tuple[List[User], List[User]]:
    return (logged_in_users(f), logged_out_users(f))

  def user_count(f) -> int:
    logged_in_users, logged_out_users = get_users()
    return len(logged_in_users) + len(logged_out_users)

Re: Lisp and Haskell (2015)

#129
post #73

Earlier quoted context omitted.

I'm not sure what "Haskell developers" are saying, but this Haskell developer says "Haskell provides many tools that can be used to solve programming woes. One such tool is its strong and flexible types system (there are several other tools, such as immutability, functional style)."

And Python provides readable syntax . Your example has an easy-to-spot bug, just from reading the code and knowing Python's semantics. Haskell's "programmable semicolon" ends up being a problem here because, thanks to typeclasses, the programmer usually does not know which semicolon they are programming under! "Python provides many tools that can be used to solve programming woes. One such tool is its strong and read…

Er, the difference here is that we're given the Python code for `getUsers` but not the Haskell code for it. That makes the error in Python obvious. The incorrect `userCount` in Python looks just as obviously correct as the incorrect `userCount` in Haskell; and conversely, if we were given the code for the Haskell `getUsers` (or even just the type signature!) the error would be just as easy to spot.

Re: Lisp and Haskell (2015)

#130
post #60

Earlier quoted context omitted.

Which is absolutely bizarre to me because most of my experience with Python has been with people who are effectively scientists who don't give a rats-ass about good coding practices and yet I rarely had issues with receiving the wrong type. Don't get me wrong though, I spent the first 10 years of programming with C and Java so I understand the comfort that a statically typed language provides. I just haven't found it…

> Frankly, if you were to ask me what the top 3 sources of my headaches in Python are, number 1, 2, and 3 would be, receiving a None value when I expected something else Curious example, because that's absolutely something a sufficiently advanced and well-thought-out static type system can completely solve. You're right that the type systems of C and Java do not meet this bar, however.

Receiving a None or Nothing or a NULL or similar is something a type system can paper over or, more politely, force you to add code to ward off but there's something happening in the actual data, if not the real world, which is causing that non-value to be present and the type system can't fix that.
Post reply on HN