Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Haskell vs C

Name: Anonymous 2009-07-16 1:19

What Haskell has which can't be implemented in few lines of C?

Name: Anonymous 2009-07-16 9:58

>>7
I lol'd

Let's try our hand at writing some Haskell in C, and go wherever it takes us. I think I'll start with tuples. C has an idiom for multiple return values (passing "out" pointers as extra arguments like in Ada procedures) but I'm going to ignore it and try to use Haskell's. A two-tuple in Haskell is just a parametrically typed container. Here's an example:

-- This will not compile but I wanted to show you the type signature
getDataAndStuff :: IO (String, Int)

main = do
  (name, age) <- getDataAndStuff
  putStrLn ("omg " ++ name ++ ", its ur " ++ (show age) ++ "th bday")

Maybe getDataAndStuff reads something from a database. Don't know, don't care. I'll use exactly the same function name for the C version. Also I could have made that string formatting a lot nicer but I couldn't be bothered.

What does the C version look like, anyway? It could look nearly the same, and be even more readable for assgoblins... Except, C doesn't have anonymous types. In fact, it doesn't have parametric types of any kind. Are we fucked? Probably not. How about this:

#include <whatthefuck.h>

typedef struct tuple2_d6f {
    char *fst;
    int snd;
} tuple2_d6f;

tuple2_d6f getDataAndStuff();

int main(int argc, char **argv) {
    tuple2_d6f temp = getDataAndStuff();
    char *strtemp = "omg %s, its ur %dth bday";
    printf(strtemp, temp.fst, temp.snd);
}

(Come to think of it, I don't even know if you can do it this way in C. Usually return values are passed in a register, I seem to recall, so that struct might have to be a struct pointer instead. Oh well.)

So, what did I accomplish here, besides wasting everyone's time only slightly less than all the other posts ever made on /prog/? I went to the trouble of making a type that will be used only once. It'll have to be defined before getDataAndStuff(), which means it will probably be off in the wet shaggy depths of a header file somewhere, which means that if I have other two-tuples floating around (as the name "tuple2_d6f" might suggest) then I might make a gruesome typo and not catch it until I compile. ...Unless I use an IDE smart enough to notice this and suggest the correction right away, which is another question altogether.

Maybe I could use a smarter naming scheme for the tuple types to help alleviate that. For example, tuple_charpt_int isn't pretty, but at least it's less ambiguous. Hell, if my preprocessor is smart enough (not every C shop uses cpp, after all) maybe I can have a neat little macro that expands into the appropriate type. Or maybe I could use a higher-level language that compiles down to C, and then not have to worry about this.

Let's dick around some more because I feel like it. The jerks at Apple made a C compiler with lambda expressions, but maybe I'm not using their anus-haxur, but I still get the strange idea that HOF in C is expressive and a smart thing to do. Most compilers won't let me make Python-style local functions, and certainly not closures. That's okay, I have a workaround:

typedef struct aids {
    FUNCTION_POINTER fn;
    void *closure;
} fake_lambda;

void *map(fake_lambda fn, void *list);

/* Now I can eat your liver! */
void *plus_one(void *closure, void *x) {
    return (void *) ((int) x) + 1;
}

void get_work_done() {
    fake_lambda f;
    f.fn = &plus_one;
    f.closure = NULL;
/* I don't really feel like finishing. */

So, any local arguments we wanted to use in the "lambda" actually have to go into a struct, whose address we then put into the fake_lambda, which then gets passed to map(), which then probably uses a macro to call the fake_lambda so as to prevent users of this mechanism from fucking up...

Or we could just use Haskell. Or seriously, any other modern language. It doesn't have to be Haskell. It just has to suck less.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List