Live data from Hacker News

Lisk — Lisp and Haskell

chrisdone.com

11–20 of 30 posts

Re: Lisk — Lisp and Haskell

#11
post #3

Not tackling pattern matching is a pretty big deficiency. Otherwise, it seems interesting, and I wonder if :i-o would really be easier to type than IO for most use cases.

I agree, it looks like :i-o is the unfortunate result of the generic hyphenation-to-capital-letter routine he has. IO should probably be a special case (:io).

Re: Lisk — Lisp and Haskell

#12
post #5

Shouldn't: def fib(n): if n Be: ... if n ? Or am I being stupid? EDIT: changed x to n.

You must mean "return n", but I don't have an opinion on "correct" behvior. All that's happening is the index is shifted by 1.

Re: Lisk — Lisp and Haskell

#13
post #10
post #8

Earlier quoted context omitted.

It's definitely wrong - just ran it in python to check in case I was missing something!

I don't think it's explicitly wrong; I've seen both fib(0) = 1 and fib(0) = 0 before. Wikipedia shows: By definition, the first two Fibonacci numbers are 0 and 1, and each subsequent number is the sum of the previous two. Some sources omit the initial 0, instead beginning the sequence with two 1s.

I think it's still wrong by that definition. I think it is just saying fib(1) is the first number, not fib(0). fib(2) should never be 2.

EDIT: Actually, I think you're right: it's just an index thing (do we start at 1 or 0) - I was confusing the index of 2 with the value of 2.

Re: Lisk — Lisp and Haskell

#14
post #7
post #6

Earlier quoted context omitted.

works with both - try it on paper

I did - with 2: fib(2) = fib(2-1) + fib(2-2) fib(2) = fib(1) + fib(0) fib(2) = 1 + 1 (rather than 1 + 0) No?

You are right, the difference is that the one sequence is " 0 1 1 2 3 5 ... " while the other is " 1 1 2 3 5 ..." - so it is just shifted by one. The interesting properties of the sequence still remain.

Re: Lisk — Lisp and Haskell

#15
post #12
post #5

Shouldn't: def fib(n): if n Be: ... if n ? Or am I being stupid? EDIT: changed x to n.

You must mean "return n", but I don't have an opinion on "correct" behvior. All that's happening is the index is shifted by 1.

True. I'll update above regarding n.

However, it's certainly different to the other examples and I would expect fib(2) to be 1 + 0 not 1 + 1.

It's a very minor point though - I think I'll stop now ;)

Re: Lisk — Lisp and Haskell

#16
I don't see how it's tackling the 'where' block--or it that would even be possible under this scheme. I find that my code is much more legible with the housekeeping and other less important helper-functions defined after the important bits. The clunky code that the author complains about can be much improved using where clauses to break it into chunks.

Taking the authors example and moving some of the processing to a where clause makes the flow much easier to follow:

    someFunction conn (Foo n) (K {x=zot}) plib = do
      withTransaction conn $ \db ->
         coconut  (fromMaybe "" $ sausages >>= bacon)

Also one of my favorite features of Haskell is using the $ as an unmatched left parenthesis, saving you from that blob of closing parenthesis that every lisp expression accumulates.

One last thing, the author complains about the ambiguity of the indentation, but doesn't make any comment about the brace & semi-colon syntax. I personally don't like it, but it should be explained why it isn't an acceptable solution.

Re: Lisk — Lisp and Haskell

#17
While programming in Haskell I also struggled with Haskell's brand of whitespace indentation, even though I come from Python. The key difference in usability between Python's whitespace indentation system and Haskell's indentation system is that you cannot start the lines in a block on the same line as the block.

Python's is more restrictive: you must skip a line before starting a multi-line indented block; i.e., this is not legal:

    if a == b: print "asdf"
        print "a"
    else:
        print "a"
This lets you decide on a very simple rule for dealing with whitespace indentation: Each new block is started by inserting a carriage return and the proper number of tabs.

Not so in Haskell, because you are given the freedom to put the first line of a block in the same line as the block starter:

    let x = 1
        y = 2

    do x 
Now you need to decide whether to be 3 or 4 spaces in depending on whether it is a let or do block. You cannot use the rule, because the appropriate number of spaces is no longer a multiple of your indentation unit.

That's just the simple case, because you are also allowed to put these block starters (let, do, case, etc) at arbitrary points in an expression:

    f = let x = 1 in let y = x + 2 in
     y + 1
This is syntactically correct Haskell; but personally I like the idea of lexical scope being represented by indentation level, which is not reflected here.

It becomes very easy to get yourself into situations where you cannot use the Python rule. But you can also impose restrictions on yourself so you _can_ use that rule. Like always treating let, do, in, etc as "{"'s in C:

    f = let
            x = 1
        in
            let
                y = x + 2
            in
                y + 1
This may look a little verbose. But in real cases there would be a lot more statements there. In the middle of all this I want to maintain the idea "number of tabs corresponds to lexical scope". We can also push the analogy to "{"'s in C and adopt the "K&R" style, but on block-starting expressions:

    f = let
        x = 1 in let
            y = x + 2 in
                y + 1

There's also the solution of editors that just figure out where to indent, in which case we can make it look pretty and still get the indentation right. I think it's best to develop a consistent style that will work across editors though.

Re: Lisk — Lisp and Haskell

#19

While programming in Haskell I also struggled with Haskell's brand of whitespace indentation, even though I come from Python. The key difference in usability between Python's whitespace indentation system and Haskell's indentation system is that you cannot start the lines in a block on the same line as the block. Python's is more restrictive: you must skip a line before starting a multi-line indented block; i.e., thi…

We use OCaml at work, which has similar syntax (although no significant indentation). We explicitly don't intend after the let. Like

  let a = 3 in
  f a
That seems alright to me, but I wonder why my intuition prefers it.

Re: Lisk — Lisp and Haskell

#20

While programming in Haskell I also struggled with Haskell's brand of whitespace indentation, even though I come from Python. The key difference in usability between Python's whitespace indentation system and Haskell's indentation system is that you cannot start the lines in a block on the same line as the block. Python's is more restrictive: you must skip a line before starting a multi-line indented block; i.e., thi…

My rule has been to just pad "do" appropriately. Almost everything else works out well with a 4-space tab. Also, don't ever use only one-or-two spaces for indentation, and if you're finding you have a long expression with so much indentation and unindentation that it gets confusing I usually find I'm doing something confusing and should simplify it anyway. For example:

    let x = y
     in do  something
            something with
                      ( lots
                      . of
                      . args
                      )
            something else
        
Is not that hard to read for me, and actually looks quite nice.

And if you're getting those terribly long-expressions, break them up. They can always be broken out in a let expression to be simpler, and with let the precedence is obvious.

    map (alpha . bravo) . filter charlie  xray  yankee >> zulu
might be better written as

    let f1     = map (alpha . bravo) . filter charlee  xray
        f2     = yankee
        result = f1  f2
     in result >> zulu
Haskell has the ability to write great one-liners, just like Perl, but it takes discipline not to use them.

Of course naming your variables descriptively helps a lot too. Examples with single-variable names are probably not the best.

Post reply on HN