Some Haskell vs. Rebol observations (and some Lisp-ness)

September 6th, 2009

It’s Sunday morning so I took some time for myself. I have a strong affinity to Functional Programming but I haven’t really done anything with Haskell yet. I read about it a lot but so far preferred OCaml for things where I wanted a compiled language.

Today I started reading Real world Haskell, I didn’t come too far yet, but I noticed two things in comparison to REBOL which I use currently the most.

Infix, Prefix and Parenthesis

Haskell seems to have a whole precedence levels going on, like c++ for example. So you don’t need parentheses in this case from the RWH book:

Function application has higher precedence than using operators, so the following two expressions have the same meaning.

ghci> (compare 2 3) == LT
True
ghci> compare 2 3 == LT
True

If I understand REBOL precedence I think it’s left to right with prefix and infix words, only infix words/operators take precedence over prefix. So the example above is one of the few code patterns where you DO need parenthesis in REBOL (let’s change it a little to some REBOL words so you can run it in REBOL shell):

>> (add 2 3) == 5
== true
>> add 2 3 == 5
** Script Error: add expected value2 argument of type: number pair char money date time tuple
** Where: halt-view
** Near: add 2 3 == 5

That’s why in this cases most rebolers use the prefix words (I think all infix words have prefix variants so you could unify this totally by using just them if you wanted).

>> equal? add 2 3 5
== true

Where you don’t need parenthesis. But if it makes your code more readable you can add them.

>> equal? (add 2 3) 5
== true

If you are a Lisp fan you can also write it like this. You can probably see now why some people call Rebol a Lisp without the parenthesis:

>> (equal? (add 2 3) 5)
== true
>> == + 2 3 5
== true
>> ( == ( + 2 3 ) 5 )
== true

equal? is prefix for == and add is prefix for + so we can write the same thing in another 2 ways, and we don’t need parens for that either:

>> equal? 2 + 3 5
== true
>> 2 + 3 == 5
== true

Function application and Parenthesis

The next example from Haskell book also shows a difference. You HAVE to add parens to this case where there is only function application.

Sometimes, however, we must use parentheses to indicate how we want a complicated expression to be parsed.

ghci> compare (sqrt 3) (sqrt 6)
LT

When REBOL is do-ing it’s code it knows how many values each function needs to consume. That’s why there are no optional function arguments in REBOL (but there are function refinements .. a very interesting feature on it’s own), and that IS the reason REBOL is Lisp without the parenthesis.

The above code does not need the parens in REBOL

>> greater? square-root 3 square-root 6
== false

We could also get all parens crazy and write it like this:

>> >> (greater? (square-root 3) (square-root 6))
== false

Code is data?

Haskell is an advanced, cutting edge research language, so I just forgot somehow that Haskells, OCaml’s and other static languages don’t give me the code-is-data/data-is-code that I got so used in Rebol. The next chapter of book started with Lists and Tuples that look like this:

ghci> head [ 1, 2, 3 ] -- a List
1
ghci> fst (1, 'a') -- a Tuple
1
ghci> snd (1, 'a')
'a'

Oh, no… the comma hell all over again!!! If any advanced language NEEDS to use commas it should at least make it like this to have a consistent, repeatable format.. we are programming here, not writing a letter to our grandma!?!

ghci> head [ 1, 2, 3, ]

:1:11: parse error on input `]'

head / fst / snd / ?? .. I won’t even go into this..

ghci> snd (1, 'a', 2)

:1:4:
    Couldn't match expected type `(a, b)'
           against inferred type `(t, Char, t1)'
    In the first argument of `snd', namely `(1, 'a', 2
    In the expression: snd (1, 'a', 2)
    In the definition of `it': it = snd (1, 'a', 2)

In REBOL, you don’t need tuples, lists (and other N data structures). In REBOL you have just series (sometimes they are also called blocks).

>> first [ 1 2 3 ]
== 1
>> first [ 1 "a" ]
== 1
>> second [ 1 "a" ] ; no comma noise btw!
== "a"

Everything is a series! (yes even that line that I input into shell is a series that is then do-ed). Series can hold anything, besides regular value types also words, lit-words, get-words… etc. and you have tons of words that work on all those series of anything. Let’s do something stupid

>> foo: [ join "Hello" "World" ]
>> insert foo 'print
>> probe foo
[print join "Hello" "World"]
>> if true foo
HelloWorld

This is probably moving into the theme of static vs. dynamic languages and I guess there are only Lisps, Schemes, Factor and REBOL for me if I want cid/dic. So far for now…

Reblog this post [with Zemanta]
Read and let read :)
  • del.icio.us
  • Reddit
  • Digg
  • DZone
  • email
  • Facebook
  • HackerNews
  • Twitter
  • StumbleUpon

4 Responses to “Some Haskell vs. Rebol observations (and some Lisp-ness)”

  1. Gustavs Says:

    It very much sounds like you’re trying to put down the staticness of Haskell.

    While your observations are true, the point is that Rebol is a dynamic language, and is meant to be suitable for different programming concepts. Blocks and the items contained all have representational overhead so that you could do the things you can.
    It’s no more sensible to brag about how you validly can set the billionth index of an array in JS while the same terminates in C++.

    Haskell, as opposed to Rebol, goes for advantages in efficiency and type safety, which, aside from helping avoid errors, allows further performance optimizations to be done safely to seemingly naive-looking code.

    As for function application syntax, since Haskell often deals with higher-order functions and partial applications, it makes sense to explicitly group applications. In case you haven’t noticed, the syntax is inspired by algebraic notation where say ab+c represents (a * b) + c

    Lastly, I don’t see how you can complain about the syntax of (a,b,c). It’s used in mathematics and many programming languages. If you would like truly brief and elegant syntax, why not write in APL or J.

    So in the end, I hope you only intended to remark on some difficulties that arose when putting down Rebol after a period of becoming used to it.

    There will always be difficulties when encountering languages with different mechanisms, but these mechanisms teach us new ways to think of things, which is why we study them.
    Because personally I believe Haskell has a lot more to teach one about programming than say Rebol or Ruby.

  2. Maxim Says:

    having learned many languages for various reasons, I find myself in a mixed feeling about both the original post and Gustav’s reply.

    You are both right ;-)

    Any language… C, assembly, English, Esperanto, REBOL, Lisp has to live with the history of its origin and the focus of its design.

    In defense of REBOL, IMHO the main focus of its design was specifically its syntax, or rather its lack of it, in exchange for a more expressive and contextual semantic. There are sooo few syntactic rules that its easy to assume its missing a lot of things and its hard for many entrenched programmers to *get it*.

    my old metaphor of mine comes to mind….. which is easier to get from point a to point b… the open field or the open road?

    Ah its an impossible question to answer… as are ALL of the language wars debates. It always depends on where you want to go (do you know the destination or only its name), how much you know of the terrain (do you have a map or directions) and the means you have to get there (on foot, using a car, a bicycle? an ATV).

    When REBOL was designed, it had very clear principles… most of which still exist in the redesigned version being spawned as we speek, a.k.a. R3.

    While I don’t personally love or was able to get much done in Haskell, I can vouch that its existence allows many people to reach their goal faster. Its purpose clear and its implementation pretty pure.

    REBOL’s main focus was its syntax. Its a “beautifull” language, which reads like no other, and is much closer to human grammar than other General Purpose Languages. The concept of context is tightly knit into its fabric, DSLs, prototypes, the richest datatype collection I have seen, lexical representations for all datatypes, this and much more, means it allows many people to get work done faster. Its simple, but don’t interchange simple with incapable, they aren’t synonyms.

    While I don’t agree that your closing statement is true, I do understand it. REBOL is closer to the open field than the open road. Its much harder to see and grasp its depth. Its one of the rare attempts in modern computing to truely start a language with a fresh slate and not assume any of the current givens have to be adhered to again.

    Commas, typed variables, scopes, class based OOP, parens, operator precedence, the lack of any statements, these where rejected in favor of functions as first class datatypes, symbolic words instead of variables, code as payload data, run-time binding, and more… these are all things which set it a part from the mainstream, in fact, more of “newer” languages (compiled or not) share in this direction than not. REBOL cannot be compiled (and some have tried, believe me) simply because of the way it handles data and code. These are organic concepts and often the line blurs between them to a point that you cannot clearly differentiate between them. Yet it still works and very well I must add.

    I’ll take just a single aspect of the language which is often frowned upon by C coders because they have a false sense of security about it, namely the fact that statically typed variables are more secure and robust.

    Some research has shown this to be the contrary. They can actually become an impediment to actual application stability cause it requires much more time to maintain than it actually adds in robustness in practice. If you have levels of magnitudes more time to track bugs in the algorithms because you have less code to manage, you end up with much better software. Code written in REBOL *Expects* the datatype to be run-time manipulated, and most applications become so much more robust because of it. They leverage this as the feature it is, not some lack in design as some claim it to be… this is an intentional decision… not a result of someone being incapable of adding type control to a language.

    Note that this is not a personal attack on your post. I’m not interested in starting a language war and the original author isn’t either, he was just stating the difference in mindset he had forgotten existed in other languages.

    So I think we must remember that REBOL isn’t better or worse, its simply different, very different. At any point we can argue that some specific thing about it suits us or doesn’t, but in practice, I’ve found that REBOL just gets the job done which much less hassle.

    Many solutions are tackled completely differently in REBOL than you’d normally think in other language, which is how it should be used. Just like Haskell tackles issues much differently than C because of its specifics and why its hard for many programmers to think in haskell terms.

    I’ll conclude by saying that REBOL has a lot to offer to computer science. It shows us a different perspective on computing, just like Haskell does. JSON’s author professed REBOL as being one of its main inspirations, to give you but one example that the simplicity theory does have its following and future in Computer science. :-)

    cheers!

  3. reboltutorial Says:

    Rebol has a huge syntax advantage thanks to dialect, it is now recognized by people like Martin Follow that DSL or Dialect is the way to go, so the problem is not syntax, the problem is the huge weakness of Rebol within the Real World IT Ecosystem: no libraries available for building real world applications with scalability in mind, community that tries to grow on the internet.

    Rebol Community is tiny and composed of Gurus, they forget that the huge majority of developers today know nothing about protocols for example so how do you expect them to build any decent web application without such libraries ?

  4. Gustavs Says:

    @Maxim
    Sure, I was never claiming that either is better or worse. Only defending Haskell by discussing how it is designed to approach the things pointed out in the post differently.

    I do however in turn argue with your last point, because Rebol is simple only intuitively (as opposed to in formal analysis), and as a piece of technology contributes only its fresh execution (and maybe the use of dynamic dialects), as otherwise it is like a Lisp.
    Lisp has had its influence, the present result being Ruby/Groovy. Evidently people still like solid constructs like classes and engines for ensuring their correct usage, and using encapsulation to save themselves from having to deal with many kinds of objects flying about in a mess.
    These constructs help them follow their and others’ code, which is important in big programs.

    So I don’t think Rebol can introduce much new to that scene.

    On the other hand, Haskell is simpler formally, just because of the lack of mutability. It’s focused on researching the composition of practical programs in formally describable and verifiable ways.
    In the future we will be composing entire programs from logical components declaratively, not manually writing little scripts.

    To emphasize, it’s not that Rebol isn’t suited for me or anything such, I’m a good hacker myself and I like Rebol as a tool, I just know that I won’t learn anything from it, as I won’t from staring at Javascript spaghetti.

    Yet I will from Haskell.

Leave a Reply