$Id: README 17 2006-09-17 18:03:15Z prelude $
WARNING The project is still in a very preliminary state. Only List was partially implemented. Feel free to contribute.
Project home is at rubyforge.org/projects/prelude/
The general idea is that functional programming provides many benefits, which are not directly available in Ruby out of the box. This library will, hopefully, provide an infrastructure for the use of most Haskell’s functional idioms. It will also facilitate a more or less direct port to Ruby of algorithms and data structures already developed by functional community. I deem infinite lists, monads, and higher-level functions to be most useful functional contribution to the general purpose programming.
I do believe the old math’s maxim that "new notation leads to new results."
As of right now, i.e., release 0.0.x, the feature list is pretty much a wish list, so treat it accordingly.
Haskell’s lists are different from Ruby’s arrays in many ways. First of all, there are more operations defined on lists and the naming convention is different. Since Haskell’s (or Lisp’s) lists play a fundamental role in everything functional, their implementation seems necessary. Here are the goals for list’s implementation:
List a = List.new([1, 2, 3]) b = [3, 4, 5] List c = a+b a[1] = 10 b[2] = a[3] a << 3 << 4
…and so on.
List ones = List.new([1]) { ones } # => [1,... ] ones.take 3 # => [1, 1, 1]
This functionality is being developed by the Lazilists project, see lazylist.rubyforge.org
While implementing majority of the Lambda world is relatively trivial in Ruby, some of the recursive beauty might be lost. Consider foldl, for example. The classic recursive definition like this
def foldl(s, &block) empty? ? s : tail.foldl(block.call(s, head), &block) end
croaks on about 800+ elements integer lists, but more rubyish and compact
def foldl(s, &block) inject(s){ |a,b| block.call(a,b) } end
does not possess any of the classic’s functional elegance. It means that for practical applications Ruby’s recursions need to be fixed or somehow re-implemented in the Prelude library.
It is a very good thing, that Ruby allows functions to be good citizens including being passed to other functions and returned from them. These need to be added to complete the picture:
add5 = proc {|x| x+5} add6 = proc {|x| x+6} add11 = add5 << add6
I.e., the add5 is an absolutely generic algorithm expressed in terms of other functions as long as add5 takes as an argument and add6 returns an object for which operation + is defined.
add5 = (proc {|x,y,z| x+y+z}).curry(5) add5.call(3, 2) # => 10
More convenient syntax is desirable.
This is where all the previous trouble should start paying off allowing an application to be structured like this:
result << connect << do_something << delete_something << with(params)
Writing tutorials for monadic computations became a little industry in itself, see nomaware.com/monads/html/index.html to get started. More monadic resources are here: haskell.org/haskellwiki/Books_and_tutorials#Using_monads
These features will be nice to have in a second release of the library:
Since most of the functionality to be implemented here is defined in Haskell’s prelude package, the name Prelude seemed natural.
The latest Prelude library version can be downloaded from rubyforge.org/frs/?group_id=2096
You can install Prelude library with the following command.
% gem install prelude
Prelude library is released under the Lesser GPL license, see www.gnu.org/licenses/lgpl.txt
Please use the following:
The authors of the project were inspired by the following works: