POV-Ray : Newsgroups : povray.off-topic : Why is Haskell interesting? Server Time
13 Oct 2026 06:44:27 EDT (-0400)
  Why is Haskell interesting? (Message 1 to 50 of 87)  
Goto Latest 50 Messages Next 37 Messages >>>
From: Invisible
Subject: Why is Haskell interesting?
Date: 26 Feb 2010 09:15:29
Message: <4b87d781@news.povray.org>
If your answer is "it's not", you can probably stop reading now.

I've been thinking about the things that make Haskell interesting. Of 
course, the main one is that it's a 100% functional language (as opposed 
to an OOP/FP hybrid like Objective Camal), so if you want to see what 
functional programming is like, Haskell is the place to go. But on 
reflection, Haskell has several interesting and/or useful attributes 
which actually have little or nothing to do with functional programming.

Haskell has automatic type inference, for example. You don't *need* a 
functional language for that; you could totally do it in a normal 
language. It's just that, historically, nobody has. (I guess the sort of 
people who think about computer programs mathematically also tend to be 
the sort of people who realise that things like type signatures can be 
derived algorithmically.)

Everybody thinks that a programming language has to either have explicit 
types (Pascal, C, C++, Java, Eiffel...) or no static typing at all 
(Smalltalk, Tcl, JavaScript, every scripting language known to 
mankind...) Haskell demonstrates that there is a Third Way: static 
typing, but with the types implicit rather than explicit.

Obviously, there are times when either you NEED to be explicit - because 
the correct answer is ambiguous, because you want improved performance, 
whatever. There are also times when it's just "good style" to be 
explicit; top-level functions should usually have type signatures. But 
you don't have to write a signature for every single damned expression 
and variable you use in the entire program; the compiler will figure it out.

Another thing Haskell has is parametric polymorphism. If you write some 
code that makes data around, it shouldn't *matter* what the hell the 
type of the data is. I mean, if you don't "do" anything with it other 
than move it, what does it matter? So, for example, it should be 
possible to write a function that joins two containers together, 
regardless of what kind of element data they contain. (Obviously the 
type of the containers themselves matters, but not the type of whatever 
they contain.)

This pre-supposes that you have type-safe containers in the first place. 
In most OO languages, you just create a container of "Object", which can 
then contain anything. If you particularly want a container to contain, 
say, only Customer objects, you usually have to implement this yourself, 
by hand.

More recently, a couple of OO languages have introduced this feature 
they call "generics". Eiffel is the first language I'm aware of that did 
it, although I gather Java has it too now. What it allows you to do is 
write a class parameterised by another class; the typical case being a 
container class parameterised by the class of element it contains. (In 
Eiffel, integers and floats are classes, unlike the Java brokenness.)

The difference is that Eiffel makes this seem like some highly complex 
uber-feature that only a few people will ever need to use, in special 
circumstances. Haskell makes it trivial. Defining a parametric type 
requires barely a few keystrokes more than defining the same thing with 
no parameters.

C++ has templates, and people often compare this to generics. I'm not 
sure why. As far as I can tell, templates not even remotely similar to 
generics.

- Generics are an extension to the type system which allow the type 
checker to handle more sophisticated type signatures.

- Templates are, as best as I can tell, preprocessor macros on steriods. 
They automate the process of creating a new, seperate, class for each 
combination of parameter values. It's like copy & pasting each time you 
want a new container class, except the template preprocessor automates 
it for you. This is clearly very much more maintainable, but not the 
same as extending the type checker.

It seems that templates can also be used to do things which are 
impossible with generics (e.g., making the implementation *different* 
for certain special cases). So I'm not sure why people compare them at 
all, because they're so totally different.

Another thing Haskell has is algebraic data types. Other languages could 
have this. It probably doesn't play well with the OO method though. In 
fact, let me expand on that.

The OOP notion of classes, inheritance, substitution and so forth 
basically assumes a model where you can always extend the current class 
hierachy. For example, you initially decide what (conceptual) properties 
every widget must have and write that in an abstract class. Thereafter, 
you can always add new kinds of widget. (Or even specific kinds of 
widget, of course.) It's a system that works fairly well.

Haskell with its algebraic data types assumes that the data you're 
trying to model has a fixed, finite set of possibilities, which you can 
describe once and for all. If that sounds stupid and limiting, consider 
a binary tree. Every node in a binary tree is either a leaf node or a 
branch node. You will never, ever, need to add a new kind of node. (If 
you did, it wouldn't be a *binary tree*. It would be something else.)

So the data structure of a binary tree can be described once and for 
all. However, the operations you can perform on it is extensible; you 
can always add new operations.

Now consider the OOP case. You write an abstract "tree" class with 
concrete "leaf" and "branch" subclasses. Each time you want to do 
something new with the tree, you write an abstract method in the tree 
class and add half of the implementation to each of the two concrete 
subclasses.

In Haskell, you write one line of code which says "a tree is either a 
leaf containing an item, or a branch containing two subtrees". You then 
write as many functions as you like, which handle the leaf and branch 
cases together, in one place (not split between three places).

For a binary tree, or an abstract syntax tree, or any number of other 
simple, ridigly-defined data structures you could envisage, this 
approach is actually much better. If you're writing a compiler or 
interpretter, you don't *need* the abstract syntax tree to be 
extensible. But you probably *do* need to be able to add new program 
passes and code manipulation functions all the time. (And letting the 
data structure be parameterised is probably Very Freaking Useful. Part 
of the compiler might use strings for names, while another part might 
use some more sophisticated structure representing fully-qualified 
names, for example.)

Now let's flip this and look at widgets again. Using the ADT approach, 
you'd need a giant "widget" type capable of representing any possible 
widget. And functions that all know how to handle any possible widget. 
And the code for handling a specific widget type is scattered between 
all the widget-handling functions.

You're never ever going to need to add new functions for handling "any 
possible widget" (although you might want one for handling a *specific* 
kind of widget). But you very likely *will* want to add new types of 
widget. But, uh, you can't.

In summary:

- If you have a limited number of structures which you want to process 
in an unlimited number of ways, ADTs work best.

- If you have an unlimited number of structures which you want to 
process in a limited number of ways, a class hierachy works best.

Haskell, of course, has to go one better: Haskell has what it calls 
"classes", but really they're "interfaces". And you can add them after 
the fact. Which means you can grab a bunch of unrelated data types 
(possibly that you didn't even write) and create a single interface for 
processing them all.

The one small glitch is that Haskell demands that all types are known at 
compile-time. Which means that doing OO-style stuff where types are 
changed dynamically at run-time is a little tricky. Haskell 98 (and the 
newly-released Haskell 2010) can't do it, but there are 
widely-implemented extensions that can. It gets kinda hairy though.

Married side by side with ADTs are case expressions. Now other languages 
have case statements, but they tend to be quite feeble. In most 
languages they only work on integers; I *think* Pascal lets you use 'em 
on enumerations [but I'm not really sure]. And in C-like languages, you 
can execute multiple alternatives at once. While this is no doubt 
occasionally useful, most of the time it's just a source of 
infuriatingly hard to find bugs (i.e., you left off the "break" 
statement, so a whole bunch of code gets executed when you didn't want 
it to).

In Haskell, case expressions work on *everything*. (Everything who's 
internal structural details are in scope, anyway. These internal details 
can be hidden from client code.) What is more, they use "pattern 
matching". This powerful feature allows you to do things like determine 
whether a tree has a particular shape and pluck several deeply-burried 
substructures out of it, all in a single transparent 1-liner. For example,

   case list of
     [[x], [y,_], [z,_,_]] -> foo x y z

This checks whether "list" contains a list with exactly 3 elements, each 
of which is a sublist of length 1, 2, 3 (respectively) - and, if all 
this is the case, it fishes out the first element of each sublist and 
feeds all the data to the "foo" function. All in one easily-readble line 
of code. The alternative in Java would be something like

   if (list.length == 3)
   {
     if (list.At(0).length == 1)
     {
       int x = list.At(0).At(0);
       if (list.At(1).length == 2)
       {
         int y = list.At(1).At(0);
         if (list.At(2).length == 3)
         {
           int z = list.At(2).At(0);
           foo(x, y, z);

which is obviously a hell of a lot longer. What is more, if your Haskell 
case expression has multiple cases in it (which it usually does), 
because of the declarative form of the patterns, the compiler can 
rearrange the code so that each test need only be performed once, and 
the compiled code can proceed with the minimum number of branch 
instructions. Such things are far, far harder to do with the 
deeply-nested forest of if-statements above. (Not to mention that the 
expressions in the if-statements might actually alter the program's 
state, so changing their order may alter the program!)

Again, this probably doesn't gel too well with OOP, which states that 
each data structure ("object") should be responsible for its own 
internal substructure. In other words, you shouldn't *need* to fish out 
deeply-burried data, the intervening objects in the chain should be 
doing this for you. According to "the OO way", the only thing you should 
ever do to objects is call methods on them, not inspect them for type 
information or substructure.

But something like, say, JavaScript (which isn't really OO in the first 
place) could certainly make use of ADTs and/or pattern matching, I think.

Another big deal about Haskell is how functions are first-class. The 
fact that functions are pure makes this a really big win, but even 
without pure functions, it's still useful. (Smalltalk implements it, for 
example.) It doesn't immediately sound very interesting, but what it 
enables you to do is write a loop once, in a library somwhere, and pass 
in the "loop body" as a function.

A trivial example is a "fold". A fold takes some container (e.g., a 
list) and repeatedly applies a binary function to it. The canonical 
example is

   sum = fold (+) 0

This says that to calculate the sum of a list, you fold it using the "+" 
function, and with a starting value of 0. (This also means that the sum 
of a completely empty list is 0.) It is obvious that

   product = fold (*) 1

but there are plenty of other uses too. For example, the (++) function 
joins to lists together, and

   concat = fold (++) []

turns a list-of-lists into a single giant list. Other examples include

   minimum = fold1 min
   maximum = fold1 max

which find the minimum or maximum of a list using the binary "min" and 
"max" functions. (The "fold1" function demands that the list be 
non-empty, and doesn't require a start value.) I could go on all day, 
but it turns out almost all uniform list operations can be implemented 
as a fold of some kind.

Other languages have done this. Smalltalk is the obvious example. It has 
#do: and #collect: which are approximately equivilent to Haskell's 
"map", #select: and #reject: which are Haskell's "filter", and many 
more. Of corse, being an object-oriented language, Smalltalk makes all 
these methods work nicely for all container types, not just lists.

(Haskell hasn't copied this trick yet. At least, not in the *standard* 
libraries. It's not difficult to change container, but it's tricky to 
write code that works generically for any container.)

The other thing about first-class function is that in both Haskell and 
Smalltalk, it is utterly trivial to spawn a new thread:

   forkIO foo                                        [foo] fork

What Smalltalk doesn't do, and Haskell does, is make combining small 
functions into larger functions trivial as well. Haskell has anonymous 
"lambda functions", it has the function composition operator, it has 
curried functions, it has the dollar operator, and so on and so forth. 
All of this *could* be put into Smalltalk, or any other OO language for 
that matter. (Whether it would be efficient is a whole other matter...)

The final thing that's interesting about Haskell is the rate at which it 
changes. Haskell (or rather, GHC) implemented Software Transactional 
Memory 5 years ago. I'm not aware of any mainstream languages that have 
this yet. GHC added Data Parallel Haskell 2 years ago, and the busy PhD 
researchers are still hard at work getting it into a usable state. 
(There's even an experimental GPU backend already.) Around the same 
time, Type Families were added. (How long did it take Java to do 
Generics?) The pace of change is staggering. Lots of new and very cool 
stuff happens in Haskell first. (No doubt it will eventually all be 
stolen by lesser languages so that people still don't use Haskell itself.)


Post a reply to this message

From: Warp
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 09:25:47
Message: <4b87d9ea@news.povray.org>
Invisible <voi### [at] devnull> wrote:
> Of course, the main one is that it's a 100% functional language

  I thought that a 100% functional language has no mutable data structures
nor functions with side-effects.

> C++ has templates, and people often compare this to generics. I'm not 
> sure why. As far as I can tell, templates not even remotely similar to 
> generics.

  Yeah, templates are a lot more powerful and versatile.

> - Templates are, as best as I can tell, preprocessor macros on steriods. 
> They automate the process of creating a new, seperate, class for each 
> combination of parameter values. It's like copy & pasting each time you 
> want a new container class, except the template preprocessor automates 
> it for you. This is clearly very much more maintainable, but not the 
> same as extending the type checker.

  Templates are not used only to generate classes, but also functions and
basic types. Template parameters can also be of almost any type (classes,
basic types, other templates, etc.) Also, templates can be recursive, which
is rather huge.

  In short, templates allow compile-time polymorphism (as opposed to runtime
polymorphism in most OO and functional languages).

-- 
                                                          - Warp


Post a reply to this message

From: Invisible
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 10:13:39
Message: <4b87e523@news.povray.org>
>> Of course, the main one is that it's a 100% functional language
> 
>   I thought that a 100% functional language has no mutable data structures
> nor functions with side-effects.

Technically, Haskell is such a language. Technically, a Haskell program 
itself doesn't produce any side-effects, it just constructs a data 
structure and passes it to the Haskell Runtime System. The Haskell 
Runtime System is what performs these side-effects.

That may sound like splitting hairs, since any compiled, runnable 
Haskell program consists of your source code AND the Runtime System, 
running as a single OS entity. In practical terms, you can "in effect" 
mutate things in Haskell, and cause other side-effects. (This is of 
course quite deliberate.)

Most "functional" languages allow you to perform side-effect anywhere, 
any time you like. It is up to you to not screw this up. Haskell is 
genuinely different. All side-effects are tightly constrained and 
controlled, and the system provides strong guarantees about them. This 
is why I feel it is justified to describe Haskell as "purely functional".

(That and the fact that it clearly has no OO features, no relational 
features, no logical features, etc. It's definitely not mixed with any 
other paradigm.)

>> C++ has templates, and people often compare this to generics. I'm not 
>> sure why. As far as I can tell, templates not even remotely similar to 
>> generics.
> 
>   Yeah, templates are a lot more powerful and versatile.

This was my conclusion also.

>   Templates are not used only to generate classes, but also functions and
> basic types.

Yes, I was simplifying. (The paragraph was already bigger than I would 
have liked, given the simplicity of the basic point I was attempting to 
express.)

>   In short, templates allow compile-time polymorphism (as opposed to runtime
> polymorphism in most OO and functional languages).

Seems like a nice way to sum it up.



I also forgot to mention Template Haskell. This GHC extension allows you 
to run arbitrary Haskell code inside the compiler. It can [in principle] 
do anything normal Haskell code does - read files, open network sockets, 
etc. But it can also do things to the compiler - most obviously, it can 
generate source code and feed it into the compiler.

You could use this to (for example) read a text file containing a BNF 
grammer and generate the source code for a parser for it. But then, you 
could do that without TH; just save the source code as a text file and 
then compile it as a seperate step. The interesting part is that TH can 
query the compiler. For example, it can read the description of a 
datatype and write some boilerplate code for it. (But hey, if you need 
to write boilerplate, doesn't that just mean that your language sucks?)

C has cpp, which (as far as I know) is very primitive and not 
Turing-complete. C++ has templates, which are quite sophisticated. 
Haskell has TH, which is obviously Turing-complete. I have no idea how 
Lisp macros work, so I can't compare. (I believe Lisp macros can 
generate code at runtime, however, which TH definitely cannot do.)


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 12:15:47
Message: <4b8801c3@news.povray.org>
Invisible wrote:
> Haskell has automatic type inference, for example.

Lots of languages have this a little. In C# you can say
   var x = new Vector2(0,3);
and x gets the type Vector2.  Automatic casting in languages is a similar 
thing, methinks.

Certainly not to the large scale that Haskell does it.

> This pre-supposes that you have type-safe containers in the first place. 
> In most OO languages, you just create a container of "Object", which can 
> then contain anything. 

This hasn't been true for a decade or more. :-) Just because Java sucks, 
don't think every statically typed language sucks the same way.

> More recently, a couple of OO languages have introduced this feature 
> they call "generics". Eiffel is the first language I'm aware of that did 
> it, although I gather Java has it too now.

Java kinda sorta has it. It's *really* a container full of Objects, with 
syntactic sugar to wrap and unwrap them. (Similarly, "inner classes" are 
just regular classes with munged up names.)

> The difference is that Eiffel makes this seem like some highly complex 
> uber-feature that only a few people will ever need to use, in special 
> circumstances. 

No, Eiffel's complexity is due to inheritance. If you have an array of 
Animals, can you put a Dog in it? If you have an array of Dogs, can you pass 
it to a routine that expects an array of Animals? Can you return an array of 
Dogs from a routine declared to return an array of Animals or vice versa? If 
X multiply inherits from Y and Z, can you assign an array of X to an array of Y?

It's not the complexity of the feature as much as its interactions with 
other features of the type system.

> It seems that templates can also be used to do things which are 
> impossible with generics (e.g., making the implementation *different* 
> for certain special cases). So I'm not sure why people compare them at 
> all, because they're so totally different.

They get compared because it's as close as C++ has to having real generics, 
and C++ aficionados don't want to admit they don't have generics. ;-)

> Another thing Haskell has is algebraic data types. Other languages could 
> have this. It probably doesn't play well with the OO method though. In 
> fact, let me expand on that.

It's interesting that Eiffel is explicitly an attempt to make algebraic data 
systems on top of OOP, in a sense. Hence the invariants, preconditions, etc.

> Haskell with its algebraic data types assumes that the data you're 
> trying to model has a fixed, finite set of possibilities, which you can 
> describe once and for all. 

Integers are finite?

> Now consider the OOP case. You write an abstract "tree" class with 
> concrete "leaf" and "branch" subclasses. Each time you want to do 
> something new with the tree, you write an abstract method in the tree 
> class and add half of the implementation to each of the two concrete 
> subclasses.

I've never seen it done that way. :-)

> For a binary tree, or an abstract syntax tree, or any number of other 
> simple, ridigly-defined data structures you could envisage, this 
> approach is actually much better. 

It depends how complex your tree is vs how complex your operations. If your 
data is simple and your operations are complex, you're going to get 
different trade-offs than if your data is complex and your operations are 
simple. If a tree could have 300 different types of nodes, but you'll only 
have 3 operations, which is better?  Then invert that.

As you say, it depends what kind of extensibility you want. Add 50 new kinds 
of nodes. Add 50 new operations. OOP was envisioned as adding new kinds of 
things. New kinds of cars to a traffic simulation, new kinds of bank 
accounts to a financial analysis program, etc.

Other than that, I'm not sure I really understood what you're talking about 
in terms of "using the ADT approach" bit.

> - If you have a limited number of structures which you want to process 
> in an unlimited number of ways, ADTs work best.
> 
> - If you have an unlimited number of structures which you want to 
> process in a limited number of ways, a class hierachy works best.

Yes, that. Well, not even a "limited number of ways."  The point of OOP is 
that you can add new structures *without* changing existing structures *at 
all*.

> The one small glitch is that Haskell demands that all types are known at 
> compile-time. Which means that doing OO-style stuff where types are 
> changed dynamically at run-time is a little tricky. Haskell 98 (and the 
> newly-released Haskell 2010) can't do it, but there are 
> widely-implemented extensions that can. It gets kinda hairy though.

It also means you have to recompile everything whenever you change a type. 
Which kind of sucks when it takes several days to compile the system.

> (i.e., you left off the "break" 
> statement, so a whole bunch of code gets executed when you didn't want 
> it to).

This is one that C# finally fixed right. Every branch of a switch has to end 
with "break" or "goto". You're allowed to "goto" another case label, so you 
can emulate "falling through."  But even then, you can rearrange cases or 
insert another case anywhere in the list without breaking any existing 
cases. With a fallthrough, if you add a case without realizing the previous 
case falls through, you just broke the previous case.

> In Haskell, case expressions work on *everything*. 

Pattern matching is indeed cool in some set of circumstances.

> which is obviously a hell of a lot longer. 

Yet, oddly enough, will work on things that *aren't lists*. That's the 
point. :-)

> According to "the OO way", the only thing you should 
> ever do to objects is call methods on them, not inspect them for type 
> information or substructure.

Yep. And that's because you can substitute a new object and still use the 
same code. Your pattern match wouldn't work at all if you said "Hmmm, I'd 
like to use that same function, only with a set instead."

> But something like, say, JavaScript (which isn't really OO in the first 
> place) could certainly make use of ADTs and/or pattern matching, I think.

Huh? Javascript is about as OO as Smalltalk is. There's nothing in 
Javascript that is *not* an object.

> Another big deal about Haskell is how functions are first-class. The 
> fact that functions are pure makes this a really big win, but even 
> without pure functions, it's still useful. (Smalltalk implements it, for 
> example.) It doesn't immediately sound very interesting, but what it 
> enables you to do is write a loop once, in a library somwhere, and pass 
> in the "loop body" as a function.

Lots of languages have this, just so ya know. :-)

> Other languages have done this. Smalltalk is the obvious example. 

Smalltalk doesn't have first-class functions. It has first class blocks, 
which are closures (or continuations, more precisely). You're not passing a 
function to #do:. You're passing a stack frame.

> What Smalltalk doesn't do, and Haskell does, is make combining small 
> functions into larger functions trivial as well. 

That's because Smalltalk doesn't have functions. It has methods. And blocks. 
And continuations.

> All of this *could* be put into Smalltalk, or any other OO language for 
> that matter. (Whether it would be efficient is a whole other matter...)

Not... really.  The difference is that Haskell functions work on data, while 
Smalltalk only has objects. In other words, you can't invoke a function 
without knowing what object that "function" is a method of. (This is also 
the case for Javascript, btw.)

C# has lambdas and anonymous expressions and stuff like that. It also has 
"delegates", which is a list of pointers to object/method pairs (or just 
methods, if it's a static/class method that doesn't need an instance).

> I'm not aware of any mainstream languages that have this yet. 

Several languages have implemented this as libraries. Generally not for 
threading but for database stuff.

> (How long did it take Java to do Generics?) 

It wasn't that generics took a long time. It's that the owners of the 
language didn't want them, for whatever reason. Then, once Java was popular, 
it was impossible to change the JVM classfile format without killing what 
little momentum Java still had, so they had to be shoehorned in. See above.

I.e., it took Java a long time to do Generics *because* people cared about 
Java. ;-)

I mean, Python has explicitly said "We're going to not change anything in 
the language spec for 2 to 3 years until everyone else writing Python 
compilers/interpreters catch up."

It's easy to innovate when you have the only compiler.

> The pace of change is staggering. Lots of new and very cool 
> stuff happens in Haskell first. (No doubt it will eventually all be 
> stolen by lesser languages so that people still don't use Haskell itself.)

That's not hard to do when you have no user base you have to support.

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 12:18:53
Message: <4b88027d$1@news.povray.org>
Invisible wrote:
>   (I believe Lisp macros can
> generate code at runtime, however, which TH definitely cannot do.)

I don't think macros are still around at runtime. What they *can* do is read 
user input at compile time, so you can (for example) make up new kinds of 
literals.

Assume Haskell doesn't have the "0xABC" kind of syntax for hex literals. 
Could you add that with Haskell, or TH?

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Warp
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 12:28:12
Message: <4b8804ac@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Invisible wrote:
> > Haskell has automatic type inference, for example.

> Lots of languages have this a little. In C# you can say
>    var x = new Vector2(0,3);
> and x gets the type Vector2.  Automatic casting in languages is a similar 
> thing, methinks.

  The next C++ standard will instroduce something similar: The 'auto' type.
The idea is that since the compiler can deduce the type of the variable in
most situations, then why should the programmer have to specify it explicitly?

  Thus you will be able to write things like:

    for(auto iter = v.begin(); iter != v.end(); ++iter) ...

  The compiler can see what is the return type of v.begin(), so there's no
need for the programmer to know it. Hence he can just specify 'auto' as the
variable type.

  This will be more than just a convencience shortcut, though. For example,
it allows doing something like this:

    template<typename Container>
    void foo(const Container& container)
    {
        auto element = container[0];
        ....
    }

  The type of the element may differ from container to container, and if
you need a variable of that type, previously there was no fool-proof way
of doing that. (The usual way around this to define a typedef inside the
container named "value_type" which defines the type of the elements, but
the 'auto' keyword will eliminate the need for that.)

-- 
                                                          - Warp


Post a reply to this message

From: Captain Jack
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 12:49:13
Message: <4b880999$1@news.povray.org>
"Invisible" <voi### [at] devnull> wrote in message 
news:4b87d781@news.povray.org...
>
> If your answer is "it's not", you can probably stop reading now.

I know it's interesting to *me* because I'd never heard of it before I 
started reading this newsgroup. Always like learning something new... :-)

--
Jack


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 16:59:35
Message: <4b884447@news.povray.org>
Warp wrote:

>   Thus you will be able to write things like:
> 
>     for(auto iter = v.begin(); iter != v.end(); ++iter) ...
> 
>   The compiler can see what is the return type of v.begin(), so there's no
> need for the programmer to know it. Hence he can just specify 'auto' as the
> variable type.

That's a nice touch. Presumably this also means that if the type of "v" 
changes, you don't have to manually change the type of "iter" to match 
any more...?

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Warp
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 17:19:45
Message: <4b884901@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> Warp wrote:

> >   Thus you will be able to write things like:
> > 
> >     for(auto iter = v.begin(); iter != v.end(); ++iter) ...
> > 
> >   The compiler can see what is the return type of v.begin(), so there's no
> > need for the programmer to know it. Hence he can just specify 'auto' as the
> > variable type.

> That's a nice touch. Presumably this also means that if the type of "v" 
> changes, you don't have to manually change the type of "iter" to match 
> any more...?

  Right.

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 17:41:15
Message: <4b884e0b$1@news.povray.org>
>> Haskell has automatic type inference, for example.
> 
> Lots of languages have this a little. In C#

Just out of curiosity, just how new *is* C#?

> This hasn't been true for a decade or more. :-) Just because Java sucks, 
> don't think every statically typed language sucks the same way.

...there are statically-typed OO languages which aren't Java? [Or 
Eiffel, which nobody ever uses.]

C++ is statically-typed, but even Warp will agree it's not a 
specifically OO language; it's more of a pragmatic hybrid of styles.

>> More recently, a couple of OO languages have introduced this feature 
>> they call "generics". Eiffel is the first language I'm aware of that 
>> did it, although I gather Java has it too now.
> 
> Java kinda sorta has it. It's *really* a container full of Objects, with 
> syntactic sugar to wrap and unwrap them.

Oh dears.

> (Similarly, "inner classes" are just regular classes with munged up names.)

Yeah, that's what I would have expected.

>> The difference is that Eiffel makes this seem like some highly complex 
>> uber-feature that only a few people will ever need to use, in special 
>> circumstances. 
> 
> No, Eiffel's complexity is due to inheritance.
> 
> It's not the complexity of the feature as much as its interactions with 
> other features of the type system.

All I know is that Eiffel makes it seem like this really exotic feature 
that you "shouldn't need to use" under normal circumstances, and if you 
find yourself using it, you've probably designed your program wrong.

Even C++ templates make it seem like a pretty big deal.

Haskell, on the other hand, makes it trivial.

> It's interesting that Eiffel is explicitly an attempt to make algebraic 
> data systems on top of OOP, in a sense. Hence the invariants, 
> preconditions, etc.

Uh... what?

>> Haskell with its algebraic data types assumes that the data you're 
>> trying to model has a fixed, finite set of possibilities, which you 
>> can describe once and for all. 
> 
> Integers are finite?

They are if there fixed-precision. ;-)

In fact, if you want to be really anal, if they're stored on a computer 
that exists in the physical world, they're finite, since the amount of 
matter [and energy] in the observable universe is finite. But I'm sure 
that's not what you meant.

>> Now consider the OOP case. You write an abstract "tree" class with 
>> concrete "leaf" and "branch" subclasses. Each time you want to do 
>> something new with the tree, you write an abstract method in the tree 
>> class and add half of the implementation to each of the two concrete 
>> subclasses.
> 
> I've never seen it done that way. :-)

Oh really? So how would you do it then?

> It depends how complex your tree is vs how complex your operations.

I could have sworn I just said that. ;-)

> As you say, it depends what kind of extensibility you want. Add 50 new 
> kinds of nodes. Add 50 new operations. OOP was envisioned as adding new 
> kinds of things. New kinds of cars to a traffic simulation, new kinds of 
> bank accounts to a financial analysis program, etc.

Indeed. You do NOT want to design one giant ADT that represents every 
possible kind of bank account, and write huge monolithic functions that 
understand how to process every possible kind of bank account. It's 
non-extensible, and all the code relating to one particular type of 
account is scattered across the different account processing functions, 
so it's the wrong way to factor the problem.

My point is that there are major classes of problems which *are* the 
other way around, and for that ADTs win. For example, the parse tree of 
an expression. You are almost never going to add new types of node to 
that, but you *are* going to be adding new processing passes all the 
time. For this, Haskell's ADT + functional approach factors the problem 
"the other way", and that works out better for this kind of problem.

And when it doesn't work out right, you use interfaces and get the 
essence of the OO solution.

>> - If you have a limited number of structures which you want to process 
>> in an unlimited number of ways, ADTs work best.
>>
>> - If you have an unlimited number of structures which you want to 
>> process in a limited number of ways, a class hierachy works best.
> 
> Yes, that.

LOL!

> Well, not even a "limited number of ways."  The point of OOP 
> is that you can add new structures *without* changing existing 
> structures *at all*.

And I was pointing out that for each thing you want to do to a 
structure, you have to add new methods up and down the inheritance hierachy.

Ultimately, if you have a kind of structure that you need to perform a 
bazillion operations on, what you'll hopefully do is define a set of 
"fundamental" operations as methods of the structure itself, and define 
all the complex processing somewhere else, in terms of these more 
fundamental operations. (If you take this to the extreme, you obviously 
end up with dumb data objects, which usually isn't good OO style.)

>> The one small glitch is that Haskell demands that all types are known 
>> at compile-time. Which means that doing OO-style stuff where types are 
>> changed dynamically at run-time is a little tricky. Haskell 98 (and 
>> the newly-released Haskell 2010) can't do it, but there are 
>> widely-implemented extensions that can. It gets kinda hairy though.
> 
> It also means you have to recompile everything whenever you change a 
> type. Which kind of sucks when it takes several days to compile the system.

Are there systems in existence which actually take that long to compile?

Anyway, Haskell extensions allow you to do runtime dynamic dispatch. 
That means you don't have to recompile your code. [Although you will 
have to relink to add in the new types you want to handle, etc.] It's 
just that it pisses the type checker off, which means you can't do 
things you'd normally expect to be able to do.

(In particular, the basic ExistentialQuantification extension allows 
typesafe upcasts, but utterly prohibits *downcasts*, which could be a 
problem...)

>> (i.e., you left off the "break" statement, so a whole bunch of code 
>> gets executed when you didn't want it to).
> 
> This is one that C# finally fixed right.

Oh thank God...

> Pattern matching is indeed cool in some set of circumstances.

Aye.

(Jay. Kay. El...)

>> which is obviously a hell of a lot longer. 
> 
> Yet, oddly enough, will work on things that *aren't lists*. That's the 
> point. :-)

Well, you can pattern match on the size of the container (presuming you 
have a polymorphic "size" function to get this). It won't be quite as 
neat though, obviously.

Secondly, there's actually an experimental extension to Haskell called 
"view patterns" which allow you to create sort-of "user defined pattern 
matching". This fixes this exact problem. (And a couple of others.)

> Yep. And that's because you can substitute a new object and still use 
> the same code. Your pattern match wouldn't work at all if you said 
> "Hmmm, I'd like to use that same function, only with a set instead."

Yes, in general pattern matching is used for implementing the "methods" 
for operating on one specific type. (Although of course in Haskell they 
aren't methods, they're just normal functions.) Your polymorphic stuff 
is then implemented with function calls, not pattern matching. But see 
my previous comments.

> Huh? Javascript is about as OO as Smalltalk is. There's nothing in 
> Javascript that is *not* an object.

1. Smalltalk has classes. JavaScript does not.

2. Smalltalk has encapsulation. JavaScript does not.

>> Another big deal about Haskell is how functions are first-class.
> 
> Lots of languages have this, just so ya know. :-)

Yeah. Smalltalk, JavaScript, Tcl after a fashion. C and C++ have 
function pointers, and you can sort-of cludge the same kind of 
techniques as found in Haskell. (But you wouldn't. It would be 
horrifyingly inefficient.)

>> Other languages have done this. Smalltalk is the obvious example. 
> 
> Smalltalk doesn't have first-class functions. It has first class blocks, 
> which are closures.

I won't pretend to comprehend what the difference is, but sure.

>> What Smalltalk doesn't do, and Haskell does, is make combining small 
>> functions into larger functions trivial as well. 
> 
> That's because Smalltalk doesn't have functions. It has methods. And 
> blocks. And continuations.

Plausibly.

>> All of this *could* be put into Smalltalk, or any other OO language 
>> for that matter. (Whether it would be efficient is a whole other 
>> matter...)
> 
> Not... really.  The difference is that Haskell functions work on data, 
> while Smalltalk only has objects. In other words, you can't invoke a 
> function without knowing what object that "function" is a method of. 
> (This is also the case for Javascript, btw.)

Erm... no, not really.

   function foo(x) {...}

   var bar = foo;

   var x = bar(5);

No objects here, no methods, just assigning a function to a variable and 
using it later. You *can* make a function an object method, but you do 
not *have* to. JavaScript is like "meh, whatever, dude. I'm green."

> C# has lambdas and anonymous expressions and stuff like that. It also 
> has "delegates", which is a list of pointers to object/method pairs (or 
> just methods, if it's a static/class method that doesn't need an instance).

Eiffel has... uh... "agents"? Which are basically GUI callback 
functions, but we wouldn't want to have actual functions, would we?

>> I'm not aware of any mainstream languages that have this yet. 
> 
> Several languages have implemented this as libraries. Generally not for 
> threading but for database stuff.

Yeah. Databases have been transactional for decades, and many languages 
can access a database. But STM is all internal to the program, and 
implements multi-way blocking and conditional branching and all kinds of 
craziness.

I'd point you to the paper I just wrote about implementing it using 
locks... but then you'd have my real name. The long and short of it is, 
it boils down to running the transaction *as if* there are no other 
transactions, but not actually performing any real writes. Then, when 
we've discovered exactly what the transaction wants to do to the central 
store, we take all the locks in sorted order. So the essence of the 
whole thing is that by simulating the transaction from beginning to end, 
we solve the old "I don't know what I need to lock until I've already 
locked stuff" problem. (And make all the locking stuff the library 
author's problem, not yours.)

>> (How long did it take Java to do Generics?) 
> 
> It wasn't that generics took a long time. It's that the owners of the 
> language didn't want them, for whatever reason.

Heh, nice.

> I mean, Python has explicitly said "We're going to not change anything 
> in the language spec for 2 to 3 years until everyone else writing Python 
> compilers/interpreters catch up."
> 
> It's easy to innovate when you have the only compiler.

Haskell has a motto: "Avoid success at all costs." The meaning of this, 
of course, is that if Haskell suddenly became crazy-popular, we wouldn't 
be able to arbitrarily change it from time to time. (In reality, this 
point has already long ago been reached.)

And just FYI, there *is* more than one Haskell compiler. Actually, there 
are several - it's just that only one has a big enough team working on 
it that they produce a production-ready product. [There are people who 
*get paid money* to write GHC.] All the others are PhD projects, or 
hobbiests. At one time there were several viable production compilers, 
but most of them have gone dormant due to the dominance of GHC.

>> The pace of change is staggering. Lots of new and very cool stuff 
>> happens in Haskell first.
> 
> That's not hard to do when you have no user base you have to support.

Heh. Better not tell that to Galois.com, Well-Typed.com, the authors of 
the 1,000+ packages in the Hackage DB, or the likes of Facebook, AT&T, 
Barclays Analytics or Linspire who all apparently use Haskell internally.

Sure, Haskell is no Java, C# or PHP. But that's not to say that *nobody* 
is using it...

See below for some outdated blurb:

http://www.haskell.org/haskellwiki/Haskell_in_industry

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 18:10:41
Message: <4b8854f1@news.povray.org>
Orchid XP v8 wrote:
>>> Haskell has automatic type inference, for example.
>>
>> Lots of languages have this a little. In C#
> 
> Just out of curiosity, just how new *is* C#?

Like 7 or 8 years. Newer versions are, of course, younger.

> ...there are statically-typed OO languages which aren't Java? [Or 
> Eiffel, which nobody ever uses.]

You're trolling here, right?

> All I know is that Eiffel makes it seem like this really exotic feature 
> that you "shouldn't need to use" under normal circumstances, and if you 
> find yourself using it, you've probably designed your program wrong.

I thnk you've misread that, since one of the primary purposes in the design 
of Eiffel was to provide a language where doing this tricky thing is right.

> Haskell, on the other hand, makes it trivial.

As long as you don't have inheritance, it *is* pretty trivial.

>> Integers are finite?
> They are if there fixed-precision. ;-)

Oh. I thought Haskell had bigints. Nevermind.

>> I've never seen it done that way. :-)
> Oh really? So how would you do it then?

Generally with the same class for nodes regardless of whether they're leaves 
or not.

> My point is that there are major classes of problems which *are* the 
> other way around, and for that ADTs win. 

Yep.

> For example, the parse tree of 
> an expression. You are almost never going to add new types of node to 
> that, but you *are* going to be adding new processing passes all the 
> time. 

I'd disagree with this, but OK. I get your point. I just think this specific 
example is probably wrong.

>> It also means you have to recompile everything whenever you change a 
>> type. Which kind of sucks when it takes several days to compile the 
>> system.
> 
> Are there systems in existence which actually take that long to compile?

Yep. Hell, it takes about 3 hours to compile the toolchain and 3 hours to 
compile Qt on my machine, and that's just C and C++ without anything 
sophisticated going on.

>> Huh? Javascript is about as OO as Smalltalk is. There's nothing in 
>> Javascript that is *not* an object.
> 
> 1. Smalltalk has classes. JavaScript does not.

Yes, it does.  Not in exactly the same way, mind. What do you think
    var d = new Date()
is doing there?

> 2. Smalltalk has encapsulation. JavaScript does not.

Yes, it does.  It's just harder and pointless.

>> Smalltalk doesn't have first-class functions. It has first class 
>> blocks, which are closures.
> 
> I won't pretend to comprehend what the difference is, but sure.

A function is a piece of code. A block is a reference to a piece of code 
that when evaluated returns a closure.  It's the same difference as between 
a class and an instance, or a lambda and a closure.

> Erm... no, not really.
> 
>   function foo(x) {...}
> 
>   var bar = foo;
> 
>   var x = bar(5);
> 
> No objects here, 

Bzzzt. You just don't know javascript very well. What object do you get when 
  foo or bar references "this"?

> Eiffel has... uh... "agents"? Which are basically GUI callback 
> functions, but we wouldn't want to have actual functions, would we?

I don't remember Eiffel well enough to remember that bit.

> Yeah. Databases have been transactional for decades, and many languages 
> can access a database. But STM is all internal to the program, and 
> implements multi-way blocking and conditional branching and all kinds of 
> craziness.

Right. And it has been implemented in database access code. Like, when you 
have "cloud" services. I think Google's cloud processing arguably uses STM. 
I'm pretty sure Erlang's Mnesia database works that way too.

> Heh. Better not tell that to Galois.com, Well-Typed.com, the authors of 
> the 1,000+ packages in the Hackage DB, or the likes of Facebook, AT&T, 
> Barclays Analytics or Linspire who all apparently use Haskell internally.

I think you missed "have to" there.

> Sure, Haskell is no Java, C# or PHP. But that's not to say that *nobody* 
> is using it...

I didn't say nobody is using it. I said you don't have to support it.

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Tim Attwood
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 21:16:17
Message: <4b888071$1@news.povray.org>
> Assume Haskell doesn't have the "0xABC" kind of syntax for hex literals. 
> Could you add that with Haskell, or TH?

Haskell supports hex, octal and exponent floats. (0xff, 0o377, 0.255e+3)


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 26 Feb 2010 21:43:41
Message: <4b8886dd$1@news.povray.org>
Tim Attwood wrote:
>> Assume Haskell doesn't have the "0xABC" kind of syntax for hex 
>> literals. Could you add that with Haskell, or TH?
> 
> Haskell supports hex, octal and exponent floats. (0xff, 0o377, 0.255e+3)

Pretend it doesn't.  Could you add it?  Can you make a literal syntax for 
"list of exactly two elements" that looks like [[-{ alpha / beta }-]] or 
something?

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 04:53:01
Message: <4b88eb7d$1@news.povray.org>
Darren New wrote:

> Assume Haskell doesn't have the "0xABC" kind of syntax for hex literals. 
> Could you add that with Haskell, or TH?

You could write a function that converts an ASCII hex string into a 
number, and then pass the string to that. So you end up saying

   if x == hex "0xABC" then...

or similar.

If you use TH instead, you can write a "splice":

   if x == $(hex "0xABC") then ...

This is more typing, but the conversion to hex now happens at 
compile-time, not runtime. (It's plausible that calling a function with 
a constant will get executed at compile-time anyway, but not guaranteed. 
TH guarantees it. And if it errors, it errors at compile-time.)

Alternatively you can use the new "quasi-quoting" feature:

   if x == [$hex| 0xABC] then ...

Notice the lack of quote marks. Quasi-quoting is really intended for 
where you want to write a big long data literal, but it's too wordy. For 
example, rather than writing

   x = Expr_Define (Expr_Function (Name_Literal "Sinc") [Expr_Var 
(Name_Literal "x")]) (Expr_BinOp BinOp_Divide (Expr_Function 
(Name_Literal "Sin") [Expr_Var (Name_Literal "x")]) (Expr_Var 
(Name_Literal "x")))

(assuming I even nested all those brackets right!), you write an 
expression parser, and then do

   x = [$parser| Sinc(x) = Sin(x) / x]

and it generates the same thing, at compile-time. As well as generating 
expressions, you can also use it to generate patterns for pattern 
matching. (Your parser of course has to distinguish between expression 
variables and Haskell variables somehow...)

However, there is no way in Haskell to make it so that some arbitrary 
new string can be used as a literal, anywhere in the program. You have 
to tell the compiler what function to use to parse this stuff, one way 
or another.

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 05:01:19
Message: <4b88ed6f@news.povray.org>
>> Just out of curiosity, just how new *is* C#?
> 
> Like 7 or 8 years. Newer versions are, of course, younger.

...I feel old now. :-(

>> ...there are statically-typed OO languages which aren't Java? [Or 
>> Eiffel, which nobody ever uses.]
> 
> You're trolling here, right?

Can you come up with names?

As you can imagine, I don't really follow this stuff very closely, but 
as far as I'm aware, there aren't very many "mainstream" languages out 
there.

>> All I know is that Eiffel makes it seem like this really exotic 
>> feature that you "shouldn't need to use" under normal circumstances, 
>> and if you find yourself using it, you've probably designed your 
>> program wrong.
> 
> I thnk you've misread that, since one of the primary purposes in the 
> design of Eiffel was to provide a language where doing this tricky thing 
> is right.
> 
>> Haskell, on the other hand, makes it trivial.
> 
> As long as you don't have inheritance, it *is* pretty trivial.

The synax seemed overly complex and intimidating to me. The actual rules 
for type compatibility are fairly complicated, but seem to intuitively 
"do what you'd expect", so that's not too much of a problem.

>>> Integers are finite?
>> They are if there fixed-precision. ;-)
> 
> Oh. I thought Haskell had bigints. Nevermind.

It does. Currently powered by the GMP. (Apparently they're trying to 
change that due to licensing issues or something...)

My point is that even bigints are, technically, finite if executed on a 
physical machine. But, like I said, I'm sure that's not what you meant. ;-)

>>> I've never seen it done that way. :-)
>> Oh really? So how would you do it then?
> 
> Generally with the same class for nodes regardless of whether they're 
> leaves or not.

Right... so if leaves contain a datum and branches don't... Oh, I 
suppose you just use a null-pointer instead or something?

Well anyway, I've never seen anyone implement it that way, but I guess 
you could.

>> For example, the parse tree of an expression. You are almost never 
>> going to add new types of node to that, but you *are* going to be 
>> adding new processing passes all the time. 
> 
> I'd disagree with this, but OK. I get your point. I just think this 
> specific example is probably wrong.

I wrote a program to interpret lambda calculus expressions. You know how 
many kinds of expression there are? 3. Exactly 3. By the formal 
definition of "lambda expression". There is always 3, and there will 
never be more than 3.

The list of things I might want to *do* to a lambda expression is of 
course huge. I might want to find all its free variables, or rename all 
variables to be unique, or reduce it to normal form, or just determine 
whether it *is* in normal form, or find the maximum nesting depth, or 
convert it into a string for display, or...

>> Are there systems in existence which actually take that long to compile?
> 
> Yep. Hell, it takes about 3 hours to compile the toolchain and 3 hours 
> to compile Qt on my machine, and that's just C and C++ without anything 
> sophisticated going on.

Hmm, interesting.

I've also heard people whine that Darcs is "too slow". Which puzzles me, 
given that every operation you perform with it takes, like, 0.02 seconds 
or something.

>>> Huh? Javascript is about as OO as Smalltalk is. There's nothing in 
>>> Javascript that is *not* an object.
>>
>> 1. Smalltalk has classes. JavaScript does not.
> 
> Yes, it does.  Not in exactly the same way, mind. What do you think
>    var d = new Date()
> is doing there?

It's running a function that fills out a bunch of fields in the object. 
You can completely *change* those fields afterwards. Or you can fill out 
the fields manually. An object can be given new fields and have its 
methods changed at any time. Sure, it's an object. But it does not have 
a well-defined class.

>> 2. Smalltalk has encapsulation. JavaScript does not.
> 
> Yes, it does.  It's just harder and pointless.

In Smalltalk, object fields are accessible only from inside the object. 
This is not the case in JavaScript, and AFAIK it is not possible to make 
it the case.

>>> Smalltalk doesn't have first-class functions. It has first class 
>>> blocks, which are closures.
>>
>> I won't pretend to comprehend what the difference is, but sure.
> 
> A function is a piece of code. A block is a reference to a piece of code 
> that when evaluated returns a closure.  It's the same difference as 
> between a class and an instance, or a lambda and a closure.

What's a closure?

>> Erm... no, not really.
>>
>>   function foo(x) {...}
>>
>>   var bar = foo;
>>
>>   var x = bar(5);
>>
>> No objects here, 
> 
> Bzzzt. You just don't know javascript very well. What object do you get 
> when  foo or bar references "this"?

I have no idea. (And no obvious way of finding out...)

>> Eiffel has... uh... "agents"? Which are basically GUI callback 
>> functions, but we wouldn't want to have actual functions, would we?
> 
> I don't remember Eiffel well enough to remember that bit.

It wasn't in the original spec. They added it later, when they figured 
out that they didn't want to do the whole Java thing with a bazillion 
interfaces. I don't recall off the top of my head how it works.

> I didn't say nobody is using it. I said you don't have to support it.

Ah, right. Well, don't tell that to the Industrial Haskell Group. ;-)

(Does anyone "have to" support Java? Or C for that matter? I can imagine 
that some C compiler vendor might have paying customers to support, but 
that doesn't stop the designers of C changing the spec...)

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 12:55:19
Message: <4b895c87$1@news.povray.org>
Orchid XP v8 wrote:
>   if x == hex "0xABC" then...

That doesn't count.

>   if x == $(hex "0xABC") then ...

That's getting closer.

> Alternatively you can use the new "quasi-quoting" feature:
>   if x == [$hex| 0xABC] then ...

That's fairly close, yes.

> However, there is no way in Haskell to make it so that some arbitrary 
> new string can be used as a literal, anywhere in the program. 

LISP works it by (IIRC) passing each token to the "read macros" and seeing 
if any of them modify it, so it has to be distinguishable somehow. FORTH 
works it by literally letting you read the input stream, as well as calling 
a specific function when an unparsable word is encountered. So in FORTH, a 
literal works mostly like your quasi-quoting scheme, except there's no magic 
characters at the front or end to say "hey, this is quoted." You'd just write
    blah blah hex 0xABC blah blah
and the "hex" function would run at compile time and read input off stdin to 
determine what comes next. So the function to create string literals is the 
double-quotes character. Integers are parsed by having nobody know wtf they 
are, so you invoke the thing that says "what's this token" and the integer 
parser comes back and says "Hey, I know how to compile that!"

Even Erlang has a mechanism to pss the parse tree thru a number of routines 
each of which takes a parse tree and returns a new parse tree. It isn't 
quite as flexible as LISP or FORTH, but it lets you add parse-time features 
pretty easily, like your splice more than anything

> You have 
> to tell the compiler what function to use to parse this stuff, one way 
> or another.

Yeah, but you shouldn't be putting it inline in the stream. You should be 
able to say "anything with < on the front and > at the back should parse as 
an XML tag."

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 13:41:15
Message: <4b89674b$1@news.povray.org>
Orchid XP v8 wrote:
> Can you come up with names?

Delphi. Object-C. Ada. D. Simula. C#. Visual Basic.

Hell, even Fortran is OO for the last 10 years.

> As you can imagine, I don't really follow this stuff very closely, but 
> as far as I'm aware, there aren't very many "mainstream" languages out 
> there.

So you having heard of it is what makes it "mainstream"? ;-)

>> As long as you don't have inheritance, it *is* pretty trivial.
> 
> The synax seemed overly complex and intimidating to me.

http://en.wikipedia.org/wiki/Eiffel_%28programming_language%29#Genericity

Seems to be as straightforward as I remember. Pretty much the simplest form 
of Generics out there.

>>>> Integers are finite?
>>> They are if there fixed-precision. ;-)
>>
>> Oh. I thought Haskell had bigints. Nevermind.
> 
> It does. Currently powered by the GMP. (Apparently they're trying to 
> change that due to licensing issues or something...)
> 
> My point is that even bigints are, technically, finite if executed on a 
> physical machine. But, like I said, I'm sure that's not what you meant. ;-)

But they're not bounded in the language. They aren't fixed precision. 
They're just not infinite precision. There's no number you can give me that 
says "they work up to this value, but not any higher."

You of all folks here should understand the difference between bounded, 
unbounded, and infinite, and the distinction between the language and its 
invocation on any one machine.

> Right... so if leaves contain a datum and branches don't... Oh, I 
> suppose you just use a null-pointer instead or something?

Or a flag. Or a leaf that inherits from a branch. Or a union-like structure. 
Or, for an N-ary tree, a list of children that happens to be empty. (After 
all, a binary tree is just an N-ary tree with restrictions on what it can hold.)

> Well anyway, I've never seen anyone implement it that way, but I guess 
> you could.

Yeah, but you wouldn't want to in Haskell.

> I wrote a program to interpret lambda calculus expressions. You know how 
> many kinds of expression there are? 3. Exactly 3. By the formal 
> definition of "lambda expression". There is always 3, and there will 
> never be more than 3.

Sure. But that's why lambda expressions were invented in the first place. 
That's like looking at a Turing machine and saying "See? No need for 
object-oriented features."

http://blogs.msdn.com/ericlippert/archive/2010/02/04/how-many-passes.aspx

Lots of passes, with about half of them being needed only for new features 
in the parse tree (compared to V1 of C#, for example). In a real compiler, 
it's nowhere near as clearcut. :-)

For example,

"""
Then we run a pass that transforms expression trees into the sequence of 
factory method calls necessary to create the expression trees at runtime.

Then we run a pass that rewrites all nullable arithmetic into code that 
tests for HasValue, and so on.
"""

Neither of those passes makes sense before you've added the feature to the 
parse tree data as well.

> I've also heard people whine that Darcs is "too slow". Which puzzles me, 
> given that every operation you perform with it takes, like, 0.02 seconds 
> or something.

You're not building real systems.

> It's running a function that fills out a bunch of fields in the object. 
> You can completely *change* those fields afterwards. Or you can fill out 
> the fields manually. An object can be given new fields and have its 
> methods changed at any time. Sure, it's an object. But it does not have 
> a well-defined class.

And you can do all that in Smalltalk too. But OK, Javascript has less of a 
"class" concept than Smalltalk does. I'd say neither is as "classy" as a 
language without code modification like Java or C++.

> In Smalltalk, object fields are accessible only from inside the object. 

Not really true. You can use reflection-type stuff to get to them, such as 
in the debugger.

> This is not the case in JavaScript, and AFAIK it is not possible to make 
> it the case.

Yes, it is. You use closures instead. It's more painful, so nobody bothers.

http://www.devx.com/getHelpOn/10MinuteSolution/16467/0/page/5

Ugly, but if you really need it, you can do it. Basically, you create a new 
object within the current object and only let the current object hold a 
reference to it.

> What's a closure?

It's the value that a lambda expression returns. A "new" statement returns 
an instance, a lambda expression returns a closure.

>> Bzzzt. You just don't know javascript very well. What object do you 
>> get when  foo or bar references "this"?
> 
> I have no idea. (And no obvious way of finding out...)

Hint: It's called "window".

function foo() {...}

is the same as

window["foo"] = Function(){...}

> It wasn't in the original spec. They added it later, when they figured 
> out that they didn't want to do the whole Java thing with a bazillion 
> interfaces. 

Oh yeah. They made a big deal of it at the time. I remember.

>> I didn't say nobody is using it. I said you don't have to support it.
> Ah, right. Well, don't tell that to the Industrial Haskell Group. ;-)

OK. But the language designers don't count that as "success" and don't mind 
breaking it?  I guess if you're using Haskell you just keep the version 
you're using around as long as you need it.

> (Does anyone "have to" support Java? 

Sure.

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 14:08:59
Message: <4b896dcb@news.povray.org>
> LISP works it by (IIRC) passing each token to the "read macros" and 
> seeing if any of them modify it, so it has to be distinguishable 
> somehow.

> FORTH works it by literally letting you read the input stream, 
> as well as calling a specific function when an unparsable word is 
> encountered. So in FORTH, a literal works mostly like your quasi-quoting 
> scheme, except there's no magic characters at the front or end to say 
> "hey, this is quoted."

> Even Erlang has a mechanism to pss the parse tree thru a number of 
> routines each of which takes a parse tree and returns a new parse tree. 
> It isn't quite as flexible as LISP or FORTH, but it lets you add 
> parse-time features pretty easily, like your splice more than anything

Well, there's no law against you writing a Haskell preprocessor in 
Haskell. (Though obviously that's not quite as convinient as the 
compiler automatically running it for you.)

>> You have to tell the compiler what function to use to parse this 
>> stuff, one way or another.
> 
> Yeah, but you shouldn't be putting it inline in the stream. You should 
> be able to say "anything with < on the front and > at the back should 
> parse as an XML tag."

The way Haskell does it has advantages.

1. You can tell that stuff is quoted, and what quoting rule it's using. 
(Pointless for something like a hex number, but damned useful for a 
complex program with a dozen kinds of AST which you might want to quote.)

2. You can't accidentally write a quoting rule which changes the meaning 
of a valid Haskell fragment.

3. The new stuff can have completely different parsing rules to Haskell. 
(Presumably the Lisp, Forth and Erlang methods can't do that.)

If you could write XML tags literally, then an expression like "if x<y 
then if y>z then..." would suddenly parse as an XML tag, which would be 
a Very Bad Thing. Really, having to explicitly say you're doing weird 
stuff isn't so bad.

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 14:35:46
Message: <4b897412$1@news.povray.org>
>> Can you come up with names?
> 
> Delphi.

I thought that died 10 years ago?

> Object-C.

I thought that died when C++ came along? (Although I hear Apple still 
uses it.)

> Ada. D. Simula.

I wasn't aware those were *ever* popular.

> C#. Visual Basic.

VB is OO now?

> Hell, even Fortran is OO for the last 10 years.

People use Fortran? I thought that was only for scientific applications. 
(Or am I thinking of Forth?)

> So you having heard of it is what makes it "mainstream"? ;-)

Look at job adverts, or websites which talk about programming. They all 
mention C, C++, Java, VB, PHP, Perl, Ruby, Python. A few very new ones 
might mention C#. Occasionally you'll hear of Erlang. They don't mention 
Fortran or Ada. (Like they don't mention Pascal, Eiffel, Smalltalk or 
Haskell.)

>>> As long as you don't have inheritance, it *is* pretty trivial.
>>
>> The synax seemed overly complex and intimidating to me.
> 
> http://en.wikipedia.org/wiki/Eiffel_%28programming_language%29#Genericity
> 
> Seems to be as straightforward as I remember. Pretty much the simplest 
> form of Generics out there.

Not as simple as Haskell, but sure, I guess that is reasonably easy.

>> My point is that even bigints are, technically, finite if executed on 
>> a physical machine. But, like I said, I'm sure that's not what you 
>> meant. ;-)
> 
> But they're not bounded in the language. They aren't fixed precision. 

OK, sure. What were we debating again...?

>> Right... so if leaves contain a datum and branches don't... Oh, I 
>> suppose you just use a null-pointer instead or something?
> 
> Or a flag. Or a leaf that inherits from a branch. Or a union-like 
> structure. Or, for an N-ary tree, a list of children that happens to be 
> empty. (After all, a binary tree is just an N-ary tree with restrictions 
> on what it can hold.)

If you specifically want a binary tree, the simplest and most logical OO 
way would be to make leaves and branches different subclasses. (Unless 
every node contains a datum, in which case branch should probably be a 
subclass of leaf.) But sure, the others are possibilities. (And if you 
might want N-ary trees, then presumably you're doing to use a list or 
array or something for the children, as you say...)

>> Well anyway, I've never seen anyone implement it that way, but I guess 
>> you could.
> 
> Yeah, but you wouldn't want to in Haskell.

I meant I've never seen it done like that in an OO language. In Haskell 
you'd obviously use an ADT, since this is the intended use case.

> http://blogs.msdn.com/ericlippert/archive/2010/02/04/how-many-passes.aspx
> 
> Lots of passes, with about half of them being needed only for new 
> features in the parse tree (compared to V1 of C#, for example). In a 
> real compiler, it's nowhere near as clearcut. :-)
> 
> For example,
> 
> """
> Then we run a pass that transforms expression trees into the sequence of 
> factory method calls necessary to create the expression trees at runtime.
> 
> Then we run a pass that rewrites all nullable arithmetic into code that 
> tests for HasValue, and so on.
> """
> 
> Neither of those passes makes sense before you've added the feature to 
> the parse tree data as well.

I'm not quite comprehending the point you're trying to make.

My point is that something like a parse tree usually doesn't need to be 
dynamically extensible. If you make an extension to the language, you 
typically need to rewrite all the code for processing the parse tree 
anyway, so the fact that it's monolithic isn't too much of an issue.

> You're not building real systems.

That's what SHE said...

> And you can do all that in Smalltalk too. But OK, Javascript has less of 
> a "class" concept than Smalltalk does.

We are in agreement.

>> In Smalltalk, object fields are accessible only from inside the object. 
> 
> Not really true. You can use reflection-type stuff to get to them, such 
> as in the debugger.

And you can take a C++ program and use pointer arithmetic to access 
private member variables. Does that mean C++ doesn't provide encapsulation?

> http://www.devx.com/getHelpOn/10MinuteSolution/16467/0/page/5

"Omitting the 'this' keyword makes the variables private to the object. 
The 'var' keyword makes the property local (each object instance gets 
its own copy of the variable)."

Well, that's news to me...

>> What's a closure?
> 
> It's the value that a lambda expression returns. A "new" statement 
> returns an instance, a lambda expression returns a closure.

I still don't really understand.

>>> Bzzzt. You just don't know javascript very well.
>>
> 
> function foo() {...}
> 
> is the same as
> 
> window["foo"] = Function(){...}

OK. So in what way does this mean that "functions are not first-class"?

>>> I didn't say nobody is using it. I said you don't have to support it.
>> Ah, right. Well, don't tell that to the Industrial Haskell Group. ;-)
> 
> OK. But the language designers don't count that as "success" and don't 
> mind breaking it?

As I said, avoiding success so that they don't have to keep things 
stable actually went out the window some years ago in reality. Most 
people now *want* Haskell to succeed. (Not that I think it will...)

> I guess if you're using Haskell you just keep the 
> version you're using around as long as you need it.

Well, there's always that possibility, it's true.

(You could also write a compiler or interpretter yourself too. The spec 
is open...)

>> Does anyone "have to" support Java? 
> 
> Sure.

Oh. Really?

I can imagine there are product written in Java that somebody has to 
support, or that there are Java compilers that somebody has to support. 
But the Java language itself?

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 14:36:30
Message: <4b89743e$1@news.povray.org>
>>> which is obviously a hell of a lot longer. 
>>
>> Yet, oddly enough, will work on things that *aren't lists*. That's the 
>> point. :-)
> 
> Well, you can pattern match on the size of the container (presuming you 
> have a polymorphic "size" function to get this). It won't be quite as 
> neat though, obviously.

What was the original?

   case list of
     [[x], [y,_], [z,_,_]] -> x+y+z
     _                     -> 0

If you want it to work for other containers, you're going to have to do 
something like

   case size c of
     3 -> case (size (c ! 0), size (c ! 1), size (c ! 2)) of
            (1, 2, 3) -> (c ! 0 ! 0) + (c ! 1 ! 0) + (c ! 2 ! 0)
            _         -> 0
     _ -> 0

Which isn't nearly as nice.

> Secondly, there's actually an experimental extension to Haskell called 
> "view patterns" which allow you to create sort-of "user defined pattern 
> matching". This fixes this exact problem. (And a couple of others.)

No, apparently it doesn't. It just lets me write

   case c of
     (size -> 3) -> ...

instead of

   case size c of
     3 -> ...

How dissappointing...

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 16:57:29
Message: <4b899549$1@news.povray.org>
Orchid XP v8 wrote:
> The way Haskell does it has advantages.

No question.

> 1. You can tell that stuff is quoted, and what quoting rule it's using. 

Trivially true of LISP and FORTH, too. LISP syntax is so simple it's hard 
not to know what you're quoting, and in FORTH *everything* works that way, 
including all the "normal" stuff.

> 2. You can't accidentally write a quoting rule which changes the meaning 
> of a valid Haskell fragment.

Yeah. That's the only thing you *can* do in Erlang, which is kind of odd.

> 3. The new stuff can have completely different parsing rules to Haskell. 
> (Presumably the Lisp, Forth and Erlang methods can't do that.)

Erlang, no, because it's already parsed when you get it. FORTH and LISP, 
yes, it's exactly the point of it.  If you can read arbitrary amount of 
input off the input file as you're compiling, you can pretty much completely 
change the parsing rules.

Of course, the parsing rule for FORTH is "read up to the next whitespace, 
then run that function. Repeat."  So the whole point of FORTH is that there 
isn't any syntax beyond that defined by the libraries. (For example, the 
function to define functions, and the "if" statement, are both library 
routines.)  It can make things rough, tho.

> If you could write XML tags literally, then an expression like "if x<y 
> then if y>z then..." would suddenly parse as an XML tag, which would be 
> a Very Bad Thing. Really, having to explicitly say you're doing weird 
> stuff isn't so bad.

Yeah, that was just an example I saw. Obviously you'd have to take care. I 
haven't used Erlang enough to understand the subtleties of its mechanisms.

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Warp
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 17:07:32
Message: <4b8997a3@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
>    case size c of
>      3 -> case (size (c ! 0), size (c ! 1), size (c ! 2)) of
>             (1, 2, 3) -> (c ! 0 ! 0) + (c ! 1 ! 0) + (c ! 2 ! 0)
>             _         -> 0
>      _ -> 0

  I don't know why, but I got an irresistible urge to write some faux haskell
after seeing that.

    case closed in d by
      x -> case (open, not!, closed, yes!, 2) because
           (1, 2, 3) -> (one, two, three) + x
            hence    -> yes
      hence -> no

  To me, it makes exactly as much sense. :P

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 17:10:04
Message: <4b89983c$1@news.povray.org>
Orchid XP v8 wrote:
>> Ada. D. Simula.
> I wasn't aware those were *ever* popular.

Ada still goes strong in the areas it is designed for, like safety-critical 
firmware.

>> C#. Visual Basic.
> VB is OO now?

It always was.  Certainly VB.NET is.

>> Hell, even Fortran is OO for the last 10 years.
> People use Fortran? I thought that was only for scientific applications. 

And scientists aren't people?

> Look at job adverts, or websites which talk about programming.

That's not "mainstream", that's "popular". :-)

> If you specifically want a binary tree, the simplest and most logical OO 
> way would be to make leaves and branches different subclasses.

Not especially. What about a branch with only one child node? Is that a leaf 
or a branch? And what's the value in the second branch?

And yes, even if leaves and branches are separate classes, it doesn't mean 
that they both aren't of type "treenode", or the leaf could be a subclass of 
branch or vice versa.

> I meant I've never seen it done like that in an OO language.

You've never seen a N-ary tree in an OO language that used the same class 
for branches and leaves?  Wow.

> My point is that something like a parse tree usually doesn't need to be 
> dynamically extensible. If you make an extension to the language, you 
> typically need to rewrite all the code for processing the parse tree 
> anyway, so the fact that it's monolithic isn't too much of an issue.

I disagree. The whole point of giving you the list of passes was showing you 
how modular each pass can be, as well as showing you how modular each parse 
node type needs to be.

> And you can take a C++ program and use pointer arithmetic to access 
> private member variables. Does that mean C++ doesn't provide encapsulation?

Yes.

>>> What's a closure?
>>
>> It's the value that a lambda expression returns. A "new" statement 
>> returns an instance, a lambda expression returns a closure.
> 
> I still don't really understand.

What is this?

    (lambda (x) (x + 1))

It's a lambda expression.

    y = (lambda (x) (x + 1))

What is y?  It's a closure.

>> window["foo"] = Function(){...}
> OK. So in what way does this mean that "functions are not first-class"?

I didn't say it did. I said that everything in Javascript is an object. 
There are no functions unassociated with a corresponding instance.

OK, you said
 > The difference is that Haskell functions work on data, while Smalltalk 
only has objects. In other words, you can't invoke a function without 
knowing what object that "function" is a method of. (This is also the case 
for Javascript, btw.)

I wasn't sure what "this is also the case for javascript" meant, but I 
thought you meant you can invoke a function without knowing what object it 
is a method of. That isn't true of Javascript, altho there is a top-level 
object that serves as a global namespace.

> As I said, avoiding success so that they don't have to keep things 
> stable actually went out the window some years ago in reality. Most 
> people now *want* Haskell to succeed. (Not that I think it will...)

Fair enough.

> I can imagine there are product written in Java that somebody has to 
> support, or that there are Java compilers that somebody has to support. 
> But the Java language itself?

Well, no, there's nobody who has to support the spec, as such. I meant there 
are major systems where someone is paid to make sure the Java it's based on 
keeps working.

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 17:13:06
Message: <4b8998f2$1@news.povray.org>
>> 3. The new stuff can have completely different parsing rules to 
>> Haskell. (Presumably the Lisp, Forth and Erlang methods can't do that.)
> 
> Erlang, no, because it's already parsed when you get it. FORTH and LISP, 
> yes, it's exactly the point of it.  If you can read arbitrary amount of 
> input off the input file as you're compiling, you can pretty much 
> completely change the parsing rules.

The way you said "take each token and pass it through a macro" made it 
sound like the input stream gets tokenised first - which means if what 
you want to quote has different ideas about what constitutes a "token", 
you've got a problem.

>> If you could write XML tags literally, then an expression like "if x<y 
>> then if y>z then..." would suddenly parse as an XML tag, which would 
>> be a Very Bad Thing. Really, having to explicitly say you're doing 
>> weird stuff isn't so bad.
> 
> Yeah, that was just an example I saw. Obviously you'd have to take care. 
> I haven't used Erlang enough to understand the subtleties of its 
> mechanisms.

Square enuf.

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 17:16:33
Message: <4b8999c1$1@news.povray.org>
Orchid XP v8 wrote:
> The way you said "take each token and pass it through a macro" made it 
> sound like the input stream gets tokenised first

It gets tokenized one token at a time. Otherwise, how would your "macro" be 
able to read the input? I'm not saying "it looks at the already-parsed 
input". I'm saying "it invokes the read() function on stdin to consume input 
that was sent to the compiler". The funky syntax is never seen by the 
tokenizer (in FORTH and LISP).

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 17:19:45
Message: <4b899a81$1@news.povray.org>
Warp wrote:
> Orchid XP v8 <voi### [at] devnull> wrote:
>>    case size c of
>>      3 -> case (size (c ! 0), size (c ! 1), size (c ! 2)) of
>>             (1, 2, 3) -> (c ! 0 ! 0) + (c ! 1 ! 0) + (c ! 2 ! 0)
>>             _         -> 0
>>      _ -> 0
> 
>   I don't know why, but I got an irresistible urge to write some faux haskell
> after seeing that.
> 
>     case closed in d by
>       x -> case (open, not!, closed, yes!, 2) because
>            (1, 2, 3) -> (one, two, three) + x
>             hence    -> yes
>       hence -> no
> 
>   To me, it makes exactly as much sense. :P

I think c ! 2 is the third element of c, not unlike c[2].
switch (size(c)) {
   case 3:
     switch (size(c[0]), size(c[1]), size(c[2])) {
       case (1,2,3):
          return c[0][0] + c[1][0] + c[2][0];
       default:
          return 0;
     }
   default:
     return 0;
}

It's not *that* hard to figure out. :-)

You should look into playing around with a completely different kind of 
programming language not based on C.  Erlang or APL or something like that.

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 17:26:22
Message: <4b899c0e$1@news.povray.org>
Darren New wrote:
> Orchid XP v8 wrote:
>> The way you said "take each token and pass it through a macro" made it 
>> sound like the input stream gets tokenised first
> 
> It gets tokenized one token at a time. Otherwise, how would your "macro" 
> be able to read the input? I'm not saying "it looks at the 
> already-parsed input". I'm saying "it invokes the read() function on 
> stdin to consume input that was sent to the compiler". The funky syntax 
> is never seen by the tokenizer (in FORTH and LISP).

Tokenising isn't parsing; it's just the initial part where you split the 
input into tokens. Thing is, each language has different ideas about 
what a "token" is...

Obviously I'm never going to use Lisp or Forth, never mind macros. I'm 
just mildly curious to know whether you can implement your own 
tokenising rules or not.

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Warp
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 17:39:12
Message: <4b899f10@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> I think c ! 2 is the third element of c, not unlike c[2].

  [] is used almost universally for indexing in most languages (not only
for random access of arrays, but also eg. accessing relational sets (where
the thing inside the square brackets is the key and the return value is the
data)). Is there a logical reason why Haskell chooses an odd syntax of
"x ! y" for the same thing than most other languages express as "x[y]"?

  Using ! for the nth element is not very expressive. In mathematics ! is
usually used for factorials, in many programming languages it's used to
express logical negation (granted, not a very logical choice per se, but
quite established), and in natural languages it's used to express shouting
or to emphasize the importance of something (like "WARNING!").

  So why choose ! as "the nth element"? Did they run out of obfuscated
one-character operators and it was the only one left? Or is there a logical
reason to choose that symbol out of all possible that I'm not aware of?
(Well, I wouldn't actually be surprised if that symbol had been used for
that purpose in some weird mathematical notations eg. in some lambda
calculus or the like since the 1930's or such.)

  I know Haskells undying love for obfuscating brevity, but would it have
hurt to actually use a descriptive *name* for that function? I don't know,
like "c element_at 2" (or even "c at 2") or whatever.

  Btw, what is logical not in Haskell?

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 17:58:49
Message: <4b89a3a9$1@news.povray.org>
Orchid XP v8 wrote:
> just mildly curious to know whether you can implement your own 
> tokenising rules or not.

You're actually reading the input from the file. How could you *not* 
implement your own tokenizing rules?

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 18:04:18
Message: <4b89a4f2$1@news.povray.org>
Warp wrote:
>   [] is used almost universally for indexing in most languages

Well, most based on C syntax. The rest (Pascal, Fortran, Ada, etc) use ().

> data)). Is there a logical reason why Haskell chooses an odd syntax of
> "x ! y" for the same thing than most other languages express as "x[y]"?

I would guess it makes the thing into an infix operator, while x[y] is 
neither prefix, postfix, infix, or ... whatever.

Plus, list literals are [ ... ], so I'm guessing that x [ y ] is ambiguous 
as to whether you're calling function x with an argument htat's a 
one-element list containing y.

Now, why they picked ! instead of (say) @ is beyond me. "@" is what I've 
seen used in all the languages that make this strictly an infix operator.

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 18:05:33
Message: <4b89a53d$1@news.povray.org>
Warp wrote:

>   [] is used almost universally for indexing in most languages.

Granted.

> Is there a logical reason why Haskell chooses an odd syntax of
> "x ! y" for the same thing than most other languages express as "x[y]"?

Yeah. "x[y]" would mean a function call, where "x" is the function name, 
and the function's argument is a 1-element list containing "y".

To put it another way, Haskell uses square brackets for lists. So you 
can't use it for indexing as well.

(Well, OK, if you changed the parsing rules of the language, you could. 
You could make it so that if you want "x[y]" to be a function call, you 
*must* put a space in there, otherwise it's an index. They already do 
this with dots; "x . y" is function composition, but "x.y" is a 
qualified name.)

>   Using ! for the nth element is not very expressive. In mathematics ! is
> usually used for factorials, in many programming languages it's used to
> express logical negation (granted, not a very logical choice per se, but
> quite established), and in natural languages it's used to express shouting
> or to emphasize the importance of something (like "WARNING!").

For what it's worth, "!" is used for arrays and dictionaries. For lists 
you use "!!". This is because indexing a list is obviously an O(n) 
operation, which is bad. So if you find yourself writing "!!", you 
should probably go check that there isn't some more performant way to do 
what you're trying to do. (Like use an array or something.)

Thus, using "!!" for a list sort-of makes sense. But for an array, "!" 
is O(1), so... um...

(Small footnote: You can't have unary operators, so there's no chance of 
using "!" for factorial. Unfortunately.)

>   So why choose ! as "the nth element"? Did they run out of obfuscated
> one-character operators and it was the only one left?

...pretty much, yes.

Arguably "@" would be more logical - but that's a resurved symbol. I 
suppose you could use "@@", but that's not terribly elegant.

I suspect what _really_ happened here is that when Haskell was first 
designed, it didn't *have* indexing at all. And then later, when Haskell 
became real-world enough to need it, they wrote it as a library, and 
didn't want to change the whole syntax of the language just to support 
arrays, so they just picked an available symbol name.

>   I know Haskells undying love for obfuscating brevity, but would it have
> hurt to actually use a descriptive *name* for that function? I don't know,
> like "c element_at 2" (or even "c at 2") or whatever.

You can't do "c at 2", but there's no reason you couldn't do "c `at` 2".

(Hell, if you utter the simple incantation "at = (!)" then the above 
will suddenly work. But that's obviously not the same thing has having 
the standard libraries implement it that way...)

>   Btw, what is logical not in Haskell?

You're going to love this...

It's "not". As in "not (x == y)".

(Of course, any sane person would write "x /= y" instead. Since most 
binary comparison operations have negated versions, you don't often need 
the not operator itself.)

For completeness, AND is "&&" and OR is "||". (Since "|" is already used 
for pattern guards.) Not too unusual.

Oh, and bitwise operations [which aren't available until you import the 
necessarily library] are ".&." and ".|.". No specific reason. Bitwise 
not is "complement".

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 18:09:19
Message: <4b89a61f$1@news.povray.org>
Darren New wrote:

> I would guess it makes the thing into an infix operator, while x[y] is 
> neither prefix, postfix, infix, or ... whatever.

The word you're looking for is apparently "mixfix".

> Plus, list literals are [ ... ], so I'm guessing that x [ y ] is 
> ambiguous as to whether you're calling function x with an argument 
> htat's a one-element list containing y.

Yeah. Although like I said in my other reply, they already made 
whitespace significant in the case of the "." character. I'm guessing 
this one's a historical accident.

> Now, why they picked ! instead of (say) @ is beyond me.

That would have been a better choice, but it's already taken. (And not 
even by another library function - it's actually *reserved* in the 
syntax rules.)

You could have had "@@", but they chose "!" for whatever reason...

Then again, this is the same language that gives you "^" and "**". Wanna 
take a guess what the difference is?

Haskell is a brilliant language, but I never said it was perfect. ;-)

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Warp
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 18:28:21
Message: <4b89aa95@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> You can't do "c at 2", but there's no reason you couldn't do "c `at` 2".

  If this were C++, it would actually be "c.at(2)" (in fact, with indexable
STL containers it not only *would* be, but actually *is* like that; well, at
least if you want boundary checks that is.)

  But I suppose that since Haskell is not an OO language and its dot operator
probably means something else altogether, making it like that would probably
be difficult (and would probably require a complete syntax redesign).

> >   Btw, what is logical not in Haskell?

> You're going to love this...

> It's "not". As in "not (x == y)".

  Why suddenly have one operator be a comprehensible word? Were they
uninspired when they thought up that one? :P

-- 
                                                          - Warp


Post a reply to this message

From: Neeum Zawan
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 20:48:10
Message: <4b89cb5a$1@news.povray.org>
On 02/27/10 14:39, Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> I think c ! 2 is the third element of c, not unlike c[2].
> 
>   [] is used almost universally for indexing in most languages (not only
> for random access of arrays, but also eg. accessing relational sets (where
> the thing inside the square brackets is the key and the return value is the
> data)). Is there a logical reason why Haskell chooses an odd syntax of
> "x ! y" for the same thing than most other languages express as "x[y]"?
> 
>   Using ! for the nth element is not very expressive. In mathematics ! is
> usually used for factorials, in many programming languages it's used to
> express logical negation (granted, not a very logical choice per se, but
> quite established), and in natural languages it's used to express shouting
> or to emphasize the importance of something (like "WARNING!").
> 
>   So why choose ! as "the nth element"? Did they run out of obfuscated
> one-character operators and it was the only one left? Or is there a logical
> reason to choose that symbol out of all possible that I'm not aware of?
> (Well, I wouldn't actually be surprised if that symbol had been used for
> that purpose in some weird mathematical notations eg. in some lambda
> calculus or the like since the 1930's or such.)
> 
>   I know Haskells undying love for obfuscating brevity, but would it have
> hurt to actually use a descriptive *name* for that function? I don't know,
> like "c element_at 2" (or even "c at 2") or whatever.

	Now you know how lots of people feel when they have to learn UNIX
(command line). At some point, you just tell them, "Hey, that's the way
it is. Weird, obscure, but works, and doesn't really get in your way
once you know it".

-- 
Depend on the rabbit's foot if you will, but remember, it didn't help
the rabbit.


Post a reply to this message

From: nemesis
Subject: Re: Why is Haskell interesting?
Date: 27 Feb 2010 23:20:01
Message: <web.4b89ee9bb2efd7406d01b7150@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:
> Darren New <dne### [at] sanrrcom> wrote:
> > I think c ! 2 is the third element of c, not unlike c[2].
>
>   [] is used almost universally for indexing in most languages (not only
> for random access of arrays, but also eg. accessing relational sets (where
> the thing inside the square brackets is the key and the return value is the
> data)). Is there a logical reason why Haskell chooses an odd syntax of
> "x ! y" for the same thing than most other languages express as "x[y]"?
>
>   Using ! for the nth element is not very expressive. In mathematics ! is
> usually used for factorials, in many programming languages it's used to
> express logical negation (granted, not a very logical choice per se, but
> quite established), and in natural languages it's used to express shouting
> or to emphasize the importance of something (like "WARNING!").

Like Scheme using it to warn about bad imperative constructs, like (set! v 1) :)

>   So why choose ! as "the nth element"?

v!1 is briefer than v[1] :)


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 04:44:51
Message: <4b8a3b13$1@news.povray.org>
>> You can't do "c at 2", but there's no reason you couldn't do "c `at` 2".
> 
>   If this were C++, it would actually be "c.at(2)".

OK.

>   But I suppose that since Haskell is not an OO language and its dot operator
> probably means something else altogether, making it like that would probably
> be difficult (and would probably require a complete syntax redesign).

The dot can mean two different things. "x . y" means  function 
composition. "x.y" is a qualified name. (It means the variables "y" from 
module "x".)

>> You're going to love this...
> 
>> It's "not". As in "not (x == y)".
> 
>   Why suddenly have one operator be a comprehensible word? Were they
> uninspired when they thought up that one? :P

Heh. If you mean "why isn't it some random symbol?" then the answer is 
"you can only use symbols for *binary* functions, not *unary* functions 
such as NOT".

Oh, you're going to love this... The logical AND and OR functions are 
"&&" and "||" respectively, but Haskell *also* has functions named "and" 
and "or". They take the logical AND or OR of a list of booleans.

Hey, I said Haskell was a great language. I never said the standard 
libraries were perfect. ;-) I'm sure you can probably name a few 
unfortunately design choices of the C++ libraries too...

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 04:46:22
Message: <4b8a3b6e@news.povray.org>
Neeum Zawan wrote:

> 	Now you know how lots of people feel when they have to learn UNIX

ls, cp, mv, rn and friends. Becuase, let's face it, adding two octets to 
cp to make copy would be a crime...

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 04:51:34
Message: <4b8a3ca6$1@news.povray.org>
nemesis wrote:

>>   So why choose ! as "the nth element"?
> 
> v!1 is briefer than v[1] :)

So is v@1. But that's not what was chosen.

Personally, I'd kinda like to be able to use v[1], but hey.

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 05:04:29
Message: <4b8a3fad$1@news.povray.org>
>>    case size c of
>>      3 -> case (size (c ! 0), size (c ! 1), size (c ! 2)) of
>>             (1, 2, 3) -> (c ! 0 ! 0) + (c ! 1 ! 0) + (c ! 2 ! 0)
>>             _         -> 0
>>      _ -> 0
> 
>   I don't know why, but I got an irresistible urge to write some faux haskell
> after seeing that.
> 
>     case closed in d by
>       x -> case (open, not!, closed, yes!, 2) because
>            (1, 2, 3) -> (one, two, three) + x
>             hence    -> yes
>       hence -> no
> 
>   To me, it makes exactly as much sense. :P

It makes sense to me, but it's awfully ugly. At present I can't think of 
a way to do better...

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 05:05:27
Message: <4b8a3fe7$1@news.povray.org>
Captain Jack wrote:

> I know it's interesting to *me* because I'd never heard of it before I 
> started reading this newsgroup. Always like learning something new... :-)

Heh, yeah. People claim it's the most talked-about language on the 
Internet, but I'd never heard of it either until I had a random 
encounter one day. And I've never looked back... ;-)

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Warp
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 08:40:29
Message: <4b8a724d@news.povray.org>
Neeum Zawan <m.n### [at] ieeeorg> wrote:
>         Now you know how lots of people feel when they have to learn UNIX
> (command line). At some point, you just tell them, "Hey, that's the way
> it is. Weird, obscure, but works, and doesn't really get in your way
> once you know it".

  The difference is that unix is 43 years old and there were no established
conventions back then.

  If you develop a new programming language today, there should be a good
reason why you go against general conventions. Making it different just for
the sake of being different is not smart.

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 11:46:29
Message: <4b8a9de5$1@news.povray.org>
Warp wrote:
> Neeum Zawan <m.n### [at] ieeeorg> wrote:
>>         Now you know how lots of people feel when they have to learn UNIX
>> (command line). At some point, you just tell them, "Hey, that's the way
>> it is. Weird, obscure, but works, and doesn't really get in your way
>> once you know it".
> 
>   The difference is that unix is 43 years old and there were no established
> conventions back then.
> 
>   If you develop a new programming language today, there should be a good
> reason why you go against general conventions. Making it different just for
> the sake of being different is not smart.

Perhaps you're forgetting that Haskell is also 20 years old?

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Warp
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 11:57:19
Message: <4b8aa06e@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> Perhaps you're forgetting that Haskell is also 20 years old?

  Hence a complete newcomer as programming languages are concerned.

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 12:10:04
Message: <4b8aa36c$1@news.povray.org>
>> Perhaps you're forgetting that Haskell is also 20 years old?
> 
>   Hence a complete newcomer as programming languages are concerned.

Not nearly as new as the likes of Java, Python, Ruby, etc. But sure, not 
as ancient as Lisp or C...

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Warp
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 12:21:53
Message: <4b8aa630@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> Not nearly as new as the likes of Java

  Well if you consider 5 years older as "not *nearly* as new"... :P

> Python

  Or 1 year older in this case...

> Ruby

  Ruby is 5 years newer as well.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 14:54:25
Message: <4b8ac9f1$1@news.povray.org>
Orchid XP v8 wrote:
> Heh. If you mean "why isn't it some random symbol?" then the answer is 
> "you can only use symbols for *binary* functions, not *unary* functions 
> such as NOT".

It could be worse. It could be APL, where functions are in greek.

-- 
Darren New, San Diego CA, USA (PST)
   The question in today's corporate environment is not
   so much "what color is your parachute?" as it is
   "what color is your nose?"


Post a reply to this message

From: Warp
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 16:15:11
Message: <4b8adcdf@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> Heh. If you mean "why isn't it some random symbol?" then the answer is 
> "you can only use symbols for *binary* functions, not *unary* functions 
> such as NOT".

  How do you negate an integral or floating point value, then?

-- 
                                                          - Warp


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 16:49:27
Message: <4b8ae4e7$1@news.povray.org>
>> Heh. If you mean "why isn't it some random symbol?" then the answer is 
>> "you can only use symbols for *binary* functions, not *unary* functions 
>> such as NOT".
> 
>   How do you negate an integral or floating point value, then?

Haskell possesses exactly *one* unary operator: unary minus. (Because, 
let's face it, not having this would just be annoying.) This is 
hard-wired into the language spec, however. You cannot define new unary 
operators.

The existence of the unary minus operator causes the following glitch:

   (5+) is a function.
   (5-) is a function.
   (5*) is a function.
   (5/) is a function.
   (+5) is a function.
   (-5) is a number.
   (*5) is a function.
   (/5) is a function.

Spot the odd one out. (There's a library function named "subtract" so 
that you can write "subtract 5" instead of "(-5)" to get a function.)

And it *is* unary minus, not part of the numeric literal syntax; for 
example "-x" works just as well as "-5" does.

(Saying "-x" is equivilent to saying "negate x". In particular, since 
unary minus is a syntax quirk, you can't define it directly. You define 
"negate" directly, and the compiler does the rest. Also, just for 
giggles, the default implementation of binary minus is "x - y = x + 
(negate y)"...)

So there - aren't you sorry you asked?

You may also have noticed that "sin -5" doesn't work. That's because 
it's interpretted as *binary* minus, i.e. "sin - 5", which obviously 
doesn't type-check. And *that* is why you have to say "sin (-5)". 
Annoying, isn't it?

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: nemesis
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 17:15:01
Message: <web.4b8aea70b2efd740fa5d1ec00@news.povray.org>
Orchid XP v8 <voi### [at] devnull> wrote:
> Neeum Zawan wrote:
>
> >  Now you know how lots of people feel when they have to learn UNIX
>
> ls, cp, mv, rn and friends. Becuase, let's face it, adding two octets to
> cp to make copy would be a crime...

there were no visual text editors back then.  You entered chars and there was a
lag before they were printed.  The less chars, the less the chance of errors.
Kinda like the choice of bits too.


Post a reply to this message

From: Orchid XP v8
Subject: Re: Why is Haskell interesting?
Date: 28 Feb 2010 17:30:35
Message: <4b8aee8b$1@news.povray.org>
>> ls, cp, mv, rn and friends. Becuase, let's face it, adding two octets to
>> cp to make copy would be a crime...
> 
> there were no visual text editors back then.  You entered chars and there was a
> lag before they were printed.  The less chars, the less the chance of errors.
> Kinda like the choice of bits too.

When I was briefly in the local council offices, I went into their 
central computer room.

Now, this was 1997 or so, but I am not kidding, EVERYTHING WAS BROWN! Do 
you have any idea how long ago they stopped making computers in brown 
and cream?!?

They had a machine with a big green screen - you know, the kind where 
you can actually *see* the scanlines, and text takes a split second or 
two to actually fade off the screen. (And you can see what the most 
common message is, because it's permanently burned into the phosphor.)

Anyway, when you type on the clunky keyboard, there's a sort of 2-second 
delay, and then the character appears on the screen. Apparently the 
mainframe you're operating is actually 60 miles down the road, connected 
over some kind of telephone link. And the terminal is a *real* dumb 
terminal. o_O

I have no idea what kind of system it runs - it wasn't Unix, or at least 
didn't appear to be. But if you type in something like "lx 37f7h.b" or 
similar, the huge line printer next to it suddenly goes crazy and starts 
printing people's benefits cheques.

It wouldn't surprise me if that's how the council's computer systems 
*still* work...

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

Goto Latest 50 Messages Next 37 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.