Live data from Hacker News

Learn from Haskell - Functional, Reusable JavaScript

seanhess.github.com

41–50 of 50 posts

Re: Learn from Haskell - Functional, Reusable JavaScript

#41
post #39
post #37

Earlier quoted context omitted.

Not having to write `function` everywhere is pretty much the reason I started using CoffeeScript.

Why not just save snippets? I do this in emacs (yasnippet) all the time instead of constantly rewriting the same stub. Not knocking coffescript here, just saying that "I don't want to write a specific word" is a pretty terrible reason to pick any language over another.

I guess he also doesn't want to read it everywhere and clutter up his code.

Re: Learn from Haskell - Functional, Reusable JavaScript

#42
post #4

One bit of trouble I have with functional style programming is something like the following example: if I have an array of people with firstName and lastName properties, how would I go about returning the person with the longest full name without adding any properties directly to the objects? It is a simple map then reduce to return the maximum length, a fairly trivial modification thereof to return the full name, bu…

In Haskell there are some helper functions for these:

    longestLastname :: [Person] -> Person
    longestLastname names = maximumBy (comparing (length . lastname)) names
In general, you can do map something like

    extractProperty list = map (\x -> (f x, x)) list
Then work on the first element of the tuple (comparing for sorting etc), and at the end return the original object by extracting the second element of the tuple.

Re: Learn from Haskell - Functional, Reusable JavaScript

#43
post #4

One bit of trouble I have with functional style programming is something like the following example: if I have an array of people with firstName and lastName properties, how would I go about returning the person with the longest full name without adding any properties directly to the objects? It is a simple map then reduce to return the maximum length, a fairly trivial modification thereof to return the full name, bu…

You wouldn't use map or reduce, you'd just use recursion with an accumulator. If you absolutely insist on map/reduce, you can just use reduce, where your binary function returns whichever object has a longer full name.

Why would you write mind-boggling recursion by hand, and not use a nice combinator that comes pre-debugged?

Re: Learn from Haskell - Functional, Reusable JavaScript

#44
post #6
post #4

One bit of trouble I have with functional style programming is something like the following example: if I have an array of people with firstName and lastName properties, how would I go about returning the person with the longest full name without adding any properties directly to the objects? It is a simple map then reduce to return the maximum length, a fairly trivial modification thereof to return the full name, bu…

The map is unnecessary. Just reduce: (* assuming: val total_len : string -> int *) List.reduce seq ~f:(fun a b -> if (total_len a) > (total_len b) then a else b) It's not necessary in this case, but fold is often a lot more useful than reduce . At least the way I think of it, the type of reduce is 'a list -> ('a -> 'a -> 'a) -> 'a , whereas the type of fold is 'a list -> init:'b -> ('b -> 'a -> 'b) -> 'b . The upside…

You can use a reduce/fold here, but it goes against the notion of building your program up from smaller pieces. Functional people call this composability, normal people call it code reuse.

reduce/fold is a very general and powerful tool. In general you want to use the most specific and least powerful solution you can get away with. This spares the reader some thinking, and in theory gives the compiler more leeway. Also with less power there's less room for error.

Here a combination of maximum (or maximumBy in Haskell) and map will give you what you are looking for.

Re: Learn from Haskell - Functional, Reusable JavaScript

#45
post #4

One bit of trouble I have with functional style programming is something like the following example: if I have an array of people with firstName and lastName properties, how would I go about returning the person with the longest full name without adding any properties directly to the objects? It is a simple map then reduce to return the maximum length, a fairly trivial modification thereof to return the full name, bu…

longestName = maximumBy . comparing $ \(f,l) -> length $ f++l

That doesn't fit the bill. He was looking for comparison on a structure that holds more than just the name. (Though the right answer is very similar to what you've written.)

Re: Learn from Haskell - Functional, Reusable JavaScript

#46
post #34

Earlier quoted context omitted.

... I know that 3 is not literally function in the Haskell type system but it's an easy way to explain it to people less familiar with the language (not that I assume freyrs3 is one of those). Also, while it might be true that "people who don't know much about Haskell" often say that everything is a function, it's also the case that people who do know a lot about the language find the notion to be pedagogically usefu…

Also, the definition of an infinite list of ones ones = 1 : ones is a non-function value, but is recursively applied to itself. Might help illustrate why this is a useful notion in Haskell.

To be precise.

"ones" is not "recursively applied to itself". "ones" is not a function. "(:)" is a function.

In actuality, "ones" is both an argument and a result of the (:) function (aka "cons").

This works in Haskell because "ones" is not an atomic value or function; "ones" is a "lazy" structure, where some of the elements's values depend on other element's values, and Haskell uses a "call-by-need" graph reduction algorithm to evaluate arbitrarily complex* computations down to values, not in any sort of sraihtforward order suggested by "argument -> function -> result -> lvalue" in an imperative or strict language.

Laziness is at the core of the runtime system's model for computing a result from a program, and it's not something you can translate line-by-line from a non-lazy program, even a functional language program.

I'm not just being pedantic. Haskell (with a runtime like GHC, required for this conversation to really make sense) really is different from other programming systems. ("Programming system"! Not just "language"!).

The runtime system ("RTS") is not just a C runtime that provides a statement language and shim over OS system calls.

The RTS is not "just" a VM like Java VM.

The RTS is (metaphorically) like perl's "perl -nple" or a SQL RDBMS query planner, where the runtime is itself a program that takes your code as input and does its own extremely sophisticated computation that is not at all visible in your program's code.

[] Arbitrarily* complex, but still "causal" structures that admit at least one valid order of evaluation. Trying to define "ones = ones" or other non-disentanglable cyclic dependencies leads to a runtime failure ("" exception).

[] In some cases, the graph solver might practically fail to solve a graph that is theoretically solvable. Let's ignore that.

Re: Learn from Haskell - Functional, Reusable JavaScript

#47
post #34

Earlier quoted context omitted.

Also, the definition of an infinite list of ones ones = 1 : ones is a non-function value, but is recursively applied to itself. Might help illustrate why this is a useful notion in Haskell.

To be precise. "ones" is not "recursively applied to itself". "ones" is not a function. "(:)" is a function. In actuality, "ones" is both an argument and a result of the (:) function (aka "cons"). This works in Haskell because "ones" is not an atomic value or function; "ones" is a "lazy" structure, where some of the elements's values depend on other element's values, and Haskell uses a "call-by-need" graph reduction…

That's good info, GHC is an pretty amazing feat of engineering, there are some good summaries of STG, C--, etc for further reading:

http://darcs.haskell.org/ghc/docs/comm/the-beast/stg.html

http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler...

http://www.reddit.com/r/programming/comments/i4jb1/haskells_...

-------------

Also, Simon M started Google +ing about what he's up to

https://plus.google.com/u/0/107890464054636586545/posts

Re: Learn from Haskell - Functional, Reusable JavaScript

#48

What bothers me in this with pure JS is the verbosity of "function (arg1,arg2) {return ...;}"

The idea is that once you define "apply" and its like, you don't have to write function () { return; } inline any more. You just use library-level functions and partially apply them. These techniques reduce the number of anonymous functions you create.

Re: Learn from Haskell - Functional, Reusable JavaScript

#49
post #26
post #23

Earlier quoted context omitted.

Yes. V8 and other JS compilers optimize tail calls, but it's not guaranteed by the standard. (i think IE doesn't, for example)

I'm not sure where you got this idea. V8 does not optimize tail calls. It's easy to see this in the Chrome console, I just entered this now: var a = function(x) { if (x == 0) return 'done'; return a(x-1); }; a(100000); RangeError: Maximum call stack size exceeded http://code.google.com/p/v8/issues/detail?id=457

Wait, seriously? I didn't know that. Thanks for the link!

Guess it's time for me to stop relying on that behavior...

Re: Learn from Haskell - Functional, Reusable JavaScript

#50
post #43

Earlier quoted context omitted.

You wouldn't use map or reduce, you'd just use recursion with an accumulator. If you absolutely insist on map/reduce, you can just use reduce, where your binary function returns whichever object has a longer full name.

Why would you write mind-boggling recursion by hand, and not use a nice combinator that comes pre-debugged?

Because I had a brain fart and though "reduce" was "scan", and I didn't want to initialize an array.
Post reply on HN