Haskell confusion (81)

1 Name: #!usr/bin/anon 2005-11-05 03:09 ID:B+nCC/mJ

I'm trying to learn Haskell (for fun, of course). My only previous experience with the functional programming paradigm was playing around with Scheme a bit. I was nodding my head to "A Gentle Introduction to Haskell" until I got to this, from section 2.2, User-Defined Types:

"Note that the type of the binary data constructor Pt is a -> a -> Point a, ..."

This is from http://www.haskell.org/tutorial/goodies.html

Now, where the heck does this type come from, and what does it mean? Just a paragraph before, we learn that "-> is a type constructor: given two types t and u, t->u is the type of functions mapping elements of type t to elements of type u."

So Pt maps elements of "a -> a" to elements of "Point a"? Or does it map elements of "a" to elements of "a -> Point a"? How does either of these possibilities make any sense? Seems like it maps two elements of type "a" to a single element of type "Point a", no?

I tried the "just ignore and keep reading, hoping it will make sense later" technique, but the next section, 2.2.1, Recursive Types, defines the Branch type in a similarly baffling way. Hopefully, someone more knowledgeable here will be so kind as to clear this up for me.

2 Name: !WAHa.06x36 2005-11-05 03:26 ID:Heaven

I know fuck all about Haskell, but that sounds vaguely like curried functions to me, which is the dumbest fucking idea to come out of functional programming ever.

I just posted this so I could bitch about curried function.

3 Name: #!usr/bin/anon 2005-11-05 04:21 ID:B+nCC/mJ

Thanks, that hint was enough to do it. I looked up "currying" on the wikipedia and now I'm beginning to understand. So in fact, the data type of Pt really is a -> (a -> Point a). And also, I don't have the necessary functional programming groundwork to read that tutorial. (But I will continue to try anyway.)

Perhaps you can enlighten me on why you believe curried functions to suck? It does not seem intrinsically obvious. What's more, Google returns no hits for "currying sucks" or "curried functions suck", so the rest of the Internet is no use in this matter.

4 Name: #!usr/bin/anon 2005-11-05 04:48 ID:OHdwZ41d

I tried reading about currying a few weeks ago and my head imploded. That shit is weird. (But then, a lot of what falls under the "functional programming" heading seems weird to me: it just doesn't seem to fit my brain at all.)

5 Name: 1,3 2005-11-05 05:03 ID:B+nCC/mJ

I thought the wikipedia article was fairly easy to follow:

http://en.wikipedia.org/wiki/Currying

It's like, you want to have a function that takes two arguments, say, plus(2,4) = 6. But instead of doing it that way, you have plus(2) return a function that adds 2 to its argument, so you do (plus(2))(4) and that equals 6.

I guess you already have to be cool with the idea that functions can return functions. That was something I already understood from playing with Scheme. But other than that, currying seems a pretty straightforward concept.

What isn't straightforward is the pros and cons of currying in practice, which is why I'm interested in what >>2 has to say about the latter.

6 Name: dmpk2k!hinhT6kz2E 2005-11-05 05:07 ID:Heaven

It's a retarded notation in my opinion, but it makes sense because of the way these languages don't take multiple arguments.

I usually just take a shortcut and interpret something like "a -> b -> c" as two arguments (a and b), and a result (c).

7 Name: reppie 2005-11-05 11:00 ID:kJQGh5ky

>>5
Take a look at http://haskell.org/hawiki/Currying

BTW, the "gentle introduction to Haskell" totally sucks. You should use Hal Daume's tutorial instead: http://www.isi.edu/~hdaume/htut/tutorial.pdf

8 Name: !WAHa.06x36 2005-11-05 14:19 ID:S3bCbd+J

> It's a retarded notation in my opinion, but it makes sense because of the way these languages don't take multiple arguments.

Well, that's just the thing, isn't it? Why are these languages arbitarily forbidding multiple arguments, and then going to great lengths to re-introduce them? You could argue that it's useful to be able to create functions that have several arguments set to static values, which is true, but currying sucks at this too, because you can't set arbitary arguments, you have to set them in a specific order. In the end, it's all incredibly lame academic wanking.

Actually, what it is, is an eruv. http://en.wikipedia.org/wiki/Eruv

Orthodox Judaism forbids a number of things on the shabbat. However, this is apparently far too inconvenient to actually follow, so what is done is that a wire is strung up around an entire neighbourhood, creating a "wall" that makes the whole neighbourhood a walled-in area, where these actions are allowed.

Basically, you create an arbitary limitations, and then you spend a whole lot of effort to get around your arbiatry self-imposed limitations without technically breaking it. I think it's retarded in religious dogma, and I think it's retarded in programming languages.

9 Name: !WAHa.06x36 2005-11-05 14:47 ID:Heaven

PS: Most modern functional/imperative hybrid scripting languages (Perl, Python, Javascript, and so on) can already do partial function evaluation in a much more generic and useful fashion. They could use some syntactic sugar for it, but it does work a lot better than currying.

10 Name: #!usr/bin/anon 2005-11-05 16:17 ID:B+nCC/mJ

It makes the semantics of the language much simpler for all functions to be equivalent; I think that's the real reason for it. You do have a point about not being able to partially evaluate in an arbitrary order, though.

11 Name: !WAHa.06x36 2005-11-05 18:54 ID:Heaven

Computer in this day and age are massively complex - why on earth would you want semantics to be simple to that extent?

No, I know, silly academic dogmatics.

12 Name: #!usr/bin/anon 2005-11-05 22:12 ID:Heaven

Ah, a Perl programmer speaks.

13 Name: #!usr/bin/anon 2005-11-05 23:19 ID:B+nCC/mJ

>>11, but that is exactly why semantics should be simple. If the problem you're trying to solve is complex, why distract yourself by dealing with a big language as well?

14 Name: !WAHa.06x36 2005-11-06 01:36 ID:Heaven

>>13

Because I can solve a problem quicker if I don't have to fight the limitaitons of the language every step of the way?

15 Name: #!usr/bin/anon 2005-11-06 02:03 ID:OHdwZ41d

>>13
It's the difference between simple (easy to use) and simple (unable to express complex ideas);

>>8
>>14
Amen.

16 Name: #!usr/bin/anon 2005-11-08 18:15 ID:MM8a1853

For me, currying is nice because you can do things like map succ list instead of map (\x -> succ x) list. Or map (+1) list as opposed to map (\x -> x+1) list.

Simple constructions to build complex stuff versus complex constructions is just different philosophies in programming, I guess.

17 Name: !WAHa.06x36 2005-11-08 19:18 ID:Heaven

I don't see how the first example has anything to do with currying. Of course, I don't know the language, but I really don't see anything about that that couldn't be done just as well with syntactic sugar and no currying. For the second, are you currying infix operators? That seems questionable at best.

Overall, that's just the equivalent of syntactic sugar. Hardly a good argument for a fundamental construct.

And I realy disagree that you can dismiss things as "just" different philosophies. All philosophies are not born equal.

18 Name: #!usr/bin/anon 2005-11-09 23:41 ID:Heaven

>>17
Yes, >>16 is currying infix operators. When that is done, it is called a "section."

19 Name: #!usr/bin/anon 2005-11-11 02:43 ID:P/Wff3Bl

>>17
Well, the nice thing about it is that it doesn't need syntactic sugar for it to work (except for infix obviously).

A disadvantage with currying is that you can't have empty arguments or implied arguments or whatever they are called where you only have to enter the first argument and the second is implied. Haskell comes up with a contrived method to counter that.

20 Name: !WAHa.06x36 2005-11-11 13:03 ID:pwaUKK3K

>>19

As I said, most scripting languages can do that, without doing any currying. The syntax isn't as neat, but it does work a lot better than currying. In Javascript:

var partial=function(a,b) { some_function(1,a,2,b) }
partial(3,4);

21 Name: #!usr/bin/anon 2005-11-11 17:55 ID:Heaven

Well, duh, C can do that. As can Haskell or pretty much anything else.

22 Name: !WAHa.06x36 2005-11-11 18:12 ID:Heaven

Yes, all the more reason to not bother with currying.

Of course, most of the scripting languages also do closures, so you can do:

var something=1,other=2;
var partial=function(a,b) { some_function(something,a,other,b) }
partial(3,4);

23 Name: #!usr/bin/anon 2005-11-11 22:40 ID:Heaven

That doesn't need a closure.

/* C code */
int something=1, other=2;

void partial(int a, int b) {
some_function(something,a,other,b);
}

partial(3,4);

24 Name: !WAHa.06x36 2005-11-11 23:05 ID:Heaven

It does if you're changing the values of those variables.

That said, Javascripts closures act really strange. You often end up having to kludge them to make them work right.

25 Name: #!usr/bin/anon 2005-11-12 00:18 ID:Heaven

>>24
Changing what variables?

26 Name: !WAHa.06x36 2005-11-13 03:06 ID:Heaven

>>25

There are only two variables in that example of yours, and I was referring to both of them.

27 Name: #!usr/bin/anon 2005-11-15 23:53 ID:P/Wff3Bl

Haskell doesn't forbid multiple arguments. It has two many ways to take multiple arguments. First is currying. The second is through tuples. Or you can make your own type like a tuple and have a function take that type.

(+) :: Int -> (Int -> Int)
This addition function takes an Int which returns a function which takes an Int which returns an Int. I put the brackets in for illustration.

(+) :: (Int,Int) -> Int
This addition function takes a tuple of two Ints and returns an Int.

(+) :: (Pair Int Int) -> Int
This takes a type called Pair which holds two Ints and returns an Int.

The second way is a lot like how C takes arguments. And Haskell can do what >>22 shows too, so currying is less a limitation than a feature or an integral part of the language because Haskell comes from typed lambda calculus.

28 Name: #!usr/bin/anon 2005-11-15 23:54 ID:P/Wff3Bl

>>27
s/22/20/

29 Name: !WAHa.06x36 2005-11-16 01:39 ID:S3bCbd+J

>>27

I wasn't arguing against Haskell, just against currying. If Haskell can do all that, why does it bother with currying?

30 Name: #!usr/bin/anon 2005-11-16 04:27 ID:P/Wff3Bl

>>29
Your arguments were that it doesn't take multiple arguments and you can't set arbitrary arguments to static values. Haskell can take multiple arguments like I said in >>27. Haskell can do arbitrary arguments just like in >>20. Currying just forces setting the arguments in 1 order (but arbitrary is possible too like in >>20) which is convenient.

31 Name: dmpk2k!hinhT6kz2E 2005-11-16 06:52 ID:Heaven

A tuple is a single argument.

I don't know about Haskell, but in Ocaml taking a tuple apart is hardly as nice as having variables handed to you directly. If you want to discuss syntactic ugliness to work around multiple arguments, this is it.

This thread has been closed. You cannot post in this thread any longer.