prelude 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/TODO ADDED
@@ -0,0 +1,6 @@
1
+ = TODO list
2
+
3
+ $Id: TODO 2 2006-08-25 00:11:17Z prelude $
4
+
5
+ Please refer to the task list on Rubyforge site for all outstanding tasks, see
6
+ http://rubyforge.org/pm/?group_id=2096
@@ -0,0 +1,66 @@
1
+ #--
2
+ # This file is part of the Prelude library that provides tools to
3
+ # enable Haskell style functional programming in Ruby.
4
+ #
5
+ # http://prelude.rubyforge.org
6
+ #
7
+ # Copyright (C) 2006 APP Design, Inc.
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation; either version 2 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # This program is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License along
20
+ # with this program; if not, write to the Free Software Foundation, Inc.,
21
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
+ #++
23
+ #
24
+ # $Id: prelude.rb 2 2006-08-25 00:11:17Z prelude $
25
+
26
+ $:.unshift(File.dirname(__FILE__))
27
+
28
+ require 'prelude/list'
29
+ require 'prelude/tuple'
30
+ require 'prelude/monad'
31
+
32
+ module Prelude
33
+ VERSION='0.0.1'
34
+ end # Prelude
35
+
36
+ class Symbol
37
+
38
+ # See http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tech/Ruby/ToProc.rdoc for the detailed discussion
39
+ def to_proc
40
+ proc { |obj, *args| obj.send(self, *args) }
41
+ end
42
+
43
+ def curry(one, *args)
44
+ proc { |*args| self.to_proc.call(one, *args) }
45
+ end
46
+
47
+ end # Symbol
48
+
49
+ class Proc
50
+
51
+ # See also http://rubyforge.org/projects/rubymurray/ for an
52
+ # elaborate port of Perl's Sub::Curry library
53
+ def curry(one, *args)
54
+ proc{ |*args| self.call(one, *args)}
55
+ end
56
+
57
+ # This is will serve as an infix composition operator
58
+ def <<(*args)
59
+ if (1==args.length) && args[0].is_a?(Proc)
60
+ proc {|*a| self.call(args[0].call(*a)) }
61
+ else
62
+ self.call(*args.flatten)
63
+ end
64
+ end
65
+
66
+ end # Proc
@@ -0,0 +1,572 @@
1
+ #--
2
+ # This file is part of the Prelude library that provides tools to
3
+ # enable Haskell style functional programming in Ruby.
4
+ #
5
+ # http://prelude.rubyforge.org
6
+ #
7
+ # Copyright (C) 2006 APP Design, Inc.
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation; either version 2 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # This program is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License along
20
+ # with this program; if not, write to the Free Software Foundation, Inc.,
21
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
+ #++
23
+
24
+ module Prelude
25
+
26
+ # $Id: list.rb 2 2006-08-25 00:11:17Z prelude $
27
+ #
28
+ # This code is inspired in part by Hipster, <hipster xs4all.nl> (a.k.a. Michel
29
+ # van de Ven), and his original sketch was initially located at
30
+ # http://www.xs4all.nl/~hipster/lib/ruby/haskell
31
+ #
32
+ # This eventually needs to be implemented with lazy lists, see
33
+ # http://lazylist.rubyforge.org for details
34
+ #
35
+ # I used the signatures of Haskell's List.hs file in order not to forget to implement
36
+ # the functions defined there and to remind of what was intended.
37
+ class List < Array
38
+
39
+ # Array compatibility functions
40
+ alias array_plus +
41
+
42
+ def +(o)
43
+ List.new(self.array_plus(o))
44
+ end
45
+
46
+ # , head -- :: [a] -> a
47
+ def head
48
+ self[0]
49
+ end
50
+
51
+ # , last -- :: [a] -> a
52
+ # already defined by the Array
53
+
54
+ # , tail -- :: [a] -> [a]
55
+ def tail
56
+ self[1..-1]
57
+ end
58
+
59
+ # , init -- :: [a] -> [a]
60
+ def init
61
+ self[0..-2]
62
+ end
63
+
64
+ # , null -- :: [a] -> Bool
65
+ def null
66
+ size == 0
67
+ end
68
+
69
+ # , length -- :: [a] -> Int
70
+ # Implemented by Array
71
+
72
+ # -- * List transformations
73
+ # , map -- :: (a -> b) -> [a] -> [b]
74
+ # Implemented by Array
75
+
76
+ # , reverse -- :: [a] -> [a]
77
+ # Implemented by Array
78
+
79
+ # , intersperse -- :: a -> [a] -> [a]
80
+ def intersperse
81
+ warn "Method 'intersperse' is not implemented yet." if $VERBOSE
82
+ return []
83
+ end
84
+
85
+ # , transpose -- :: [[a]] -> [[a]]
86
+ # Implemented by Array
87
+
88
+ # -- * Reducing lists (folds)
89
+
90
+ # , foldl -- :: (a -> b -> a) -> a -> [b] -> a
91
+
92
+ # Classic recursive functional definition causes stack overflow for
93
+ # arrays of any usable size... So don't use it, it's here for
94
+ # demonstration purposes only
95
+ def f_foldl(s, &block)
96
+ empty? ? s : tail.f_foldl(block.call(s, head), &block)
97
+ end
98
+
99
+ # This is a more pedestrian iterative version.
100
+ def foldl(s, &block)
101
+ inject(s){ |a,b| block.call(a,b) }
102
+ end
103
+
104
+ # , foldl' -- :: (a -> b -> a) -> a -> [b] -> a
105
+ def foldl_
106
+ warn "Method 'foldl_' is not implemented yet." if $VERBOSE
107
+ return []
108
+ end
109
+
110
+ # , foldl1 -- :: (a -> a -> a) -> [a] -> a
111
+ def foldl1(&block)
112
+ tail.foldl(head, &block)
113
+ end
114
+
115
+ # , foldl1' -- :: (a -> a -> a) -> [a] -> a
116
+ def foldl1_
117
+ warn "Method 'foldl1_' is not implemented yet." if $VERBOSE
118
+ return []
119
+ end
120
+
121
+ # , foldr -- :: (a -> b -> b) -> b -> [a] -> b
122
+ def foldr(s, &block)
123
+ inject(s){ |a,b| block.call(b, a) }
124
+ end
125
+
126
+ # , foldr1 -- :: (a -> a -> a) -> [a] -> a
127
+ def foldr1(&block)
128
+ tail.foldr(head, &block)
129
+ end
130
+
131
+ # -- ** Special folds
132
+
133
+ # , concat -- :: [[a]] -> [a]
134
+ # Implemented by Array but semantics is different
135
+ def concat
136
+ flatten
137
+ end
138
+
139
+
140
+ # , concatMap -- :: (a -> [b]) -> [a] -> [b]
141
+ def concat_map
142
+ warn "Method 'concatMap' is not implemented yet." if $VERBOSE
143
+ return []
144
+ end
145
+ alias concatMap concat_map
146
+
147
+ # , and -- :: [Bool] -> Bool
148
+ def and
149
+ foldr(true){|x,y| x && y}
150
+ end
151
+
152
+ # , or -- :: [Bool] -> Bool
153
+ def or
154
+ foldr(false){|x,y| (x || y)}
155
+ end
156
+
157
+ # , any -- :: (a -> Bool) -> [a] -> Bool
158
+ def any(&block)
159
+ each{|e| return true if block.call(e)}
160
+ return false
161
+ end
162
+
163
+ # , all -- :: (a -> Bool) -> [a] -> Bool
164
+ def all(&block)
165
+ each{|e| return false unless block.call(e)}
166
+ return true
167
+ end
168
+
169
+ # , sum -- :: (Num a) => [a] -> a
170
+ def sum
171
+ warn "Method 'sum' is not implemented yet." if $VERBOSE
172
+ return []
173
+ end
174
+
175
+ # , product -- :: (Num a) => [a] -> a
176
+ def product
177
+ warn "Method 'product' is not implemented yet." if $VERBOSE
178
+ return []
179
+ end
180
+
181
+ # , maximum -- :: (Ord a) => [a] -> a
182
+ def maximum
183
+ warn "Method 'maximum' is not implemented yet." if $VERBOSE
184
+ return []
185
+ end
186
+
187
+ # , minimum -- :: (Ord a) => [a] -> a
188
+ def minimum
189
+ warn "Method 'minimum' is not implemented yet." if $VERBOSE
190
+ return []
191
+ end
192
+
193
+
194
+ # -- * Building lists
195
+
196
+ # -- ** Scans
197
+ # , scanl -- :: (a -> b -> a) -> a -> [b] -> [a]
198
+ def scanl(s, &block)
199
+ inject([s]){ |a,b| a << block.call(a.last,b) }
200
+ end
201
+
202
+ # , scanl1 -- :: (a -> a -> a) -> [a] -> [a]
203
+ def scanl1(&block)
204
+ tail.scanl(head, &block)
205
+ end
206
+
207
+ # , scanr -- :: (a -> b -> b) -> b -> [a] -> [b]
208
+ def scanr(s, &block)
209
+ inject([s]){ |a,b| a << block.call(b, a.last) }
210
+ end
211
+
212
+ # , scanr1 -- :: (a -> a -> a) -> [a] -> [a]
213
+ def scanr1(&block)
214
+ tail.scanr(head, &block)
215
+ end
216
+
217
+
218
+ # -- ** Accumulating maps
219
+ # , mapAccumL -- :: (a -> b -> (a,c)) -> a -> [b] -> (a,[c])
220
+ def map_accum_l
221
+ warn "Method 'map_accum_l' is not implemented yet." if $VERBOSE
222
+ return []
223
+ end
224
+ alias mapAccumL map_accum_l
225
+
226
+ # , mapAccumR -- :: (a -> b -> (a,c)) -> a -> [b] -> (a,[c])
227
+ def map_accum_r
228
+ warn "Method 'map_accum_r' is not implemented yet." if $VERBOSE
229
+ return []
230
+ end
231
+ alias mapAccumR map_accum_r
232
+
233
+
234
+ # -- ** Infinite lists
235
+ # , iterate -- :: (a -> a) -> a -> [a]
236
+ def iterate
237
+ warn "Method 'iterate' is not implemented yet." if $VERBOSE
238
+ return []
239
+ end
240
+
241
+ # , repeat -- :: a -> [a]
242
+ def repeat
243
+ warn "Method 'repeat' is not implemented yet." if $VERBOSE
244
+ return []
245
+ end
246
+
247
+ # , replicate -- :: Int -> a -> [a]
248
+ def replicate
249
+ warn "Method 'replicate' is not implemented yet." if $VERBOSE
250
+ return []
251
+ end
252
+
253
+ # , cycle -- :: [a] -> [a]
254
+ def cycle
255
+ warn "Method 'cycle' is not implemented yet." if $VERBOSE
256
+ return []
257
+ end
258
+
259
+
260
+ # -- ** Unfolding
261
+ # , unfoldr -- :: (b -> Maybe (a, b)) -> b -> [a]
262
+ def unfoldr
263
+ warn "Method 'unfoldr' is not implemented yet." if $VERBOSE
264
+ return []
265
+ end
266
+
267
+
268
+ # -- * Sublists
269
+
270
+ # -- ** Extracting sublists
271
+ # , take -- :: Int -> [a] -> [a]
272
+ def take(n)
273
+ self[0..(n-1)]
274
+ end
275
+
276
+ # , drop -- :: Int -> [a] -> [a]
277
+ def drop(n)
278
+ self[n..-1]
279
+ end
280
+
281
+ # , splitAt -- :: Int -> [a] -> ([a], [a])
282
+ def split_at(n)
283
+ [take(n), drop(n)]
284
+ end
285
+ alias splitAt split_at
286
+
287
+ # , takeWhile -- :: (a -> Bool) -> [a] -> [a]
288
+ def take_while
289
+ r = []
290
+ each{ |e|
291
+ break unless yield(e)
292
+ r << e
293
+ }
294
+ r
295
+ end
296
+ alias takeWhile take_while
297
+
298
+ # , dropWhile -- :: (a -> Bool) -> [a] -> [a]
299
+ def drop_while
300
+ r = []
301
+ each{ |e|
302
+ next if yield(e)
303
+ r << e
304
+ }
305
+ r
306
+ end
307
+ alias dropWhile drop_while
308
+
309
+ # , span -- :: (a -> Bool) -> [a] -> ([a], [a])
310
+ def span(&block)
311
+ [take_while(&block), drop_while(&block)]
312
+ end
313
+
314
+ # , break -- :: (a -> Bool) -> [a] -> ([a], [a])
315
+ def break
316
+ warn "Method 'break' is not implemented yet." if $VERBOSE
317
+ return []
318
+ end
319
+
320
+ # , group -- :: Eq a => [a] -> [[a]]
321
+ def group
322
+ warn "Method 'group' is not implemented yet." if $VERBOSE
323
+ return []
324
+ end
325
+
326
+ # , inits -- :: [a] -> [[a]]
327
+ def inits
328
+ warn "Method 'inits' is not implemented yet." if $VERBOSE
329
+ return []
330
+ end
331
+
332
+ # , tails -- :: [a] -> [[a]]
333
+ def tails
334
+ warn "Method 'tails' is not implemented yet." if $VERBOSE
335
+ return []
336
+ end
337
+
338
+ # -- ** Predicates
339
+ # , isPrefixOf -- :: (Eq a) => [a] -> [a] -> Bool
340
+ def is_prefix_of
341
+ warn "Method 'is_prefix_of' is not implemented yet." if $VERBOSE
342
+ return []
343
+ end
344
+ alias isPrefixOf is_prefix_of
345
+
346
+ # , isSuffixOf -- :: (Eq a) => [a] -> [a] -> Bool
347
+ def is_suffix_of
348
+ warn "Method 'is_suffix_of' is not implemented yet." if $VERBOSE
349
+ return []
350
+ end
351
+ alias isSuffixOf is_suffix_of
352
+
353
+ # -- * Searching lists
354
+
355
+ # -- ** Searching by equality
356
+ # , elem -- :: a -> [a] -> Bool
357
+ def elem
358
+ warn "Method 'elem' is not implemented yet." if $VERBOSE
359
+ return []
360
+ end
361
+
362
+ # , notElem -- :: a -> [a] -> Bool
363
+ def not_elem
364
+ warn "Method 'not_elem' is not implemented yet." if $VERBOSE
365
+ return []
366
+ end
367
+ alias notElem not_elem
368
+
369
+ # , lookup -- :: (Eq a) => a -> [(a,b)] -> Maybe b
370
+ def lookup
371
+ warn "Method 'lookup' is not implemented yet." if $VERBOSE
372
+ return []
373
+ end
374
+
375
+ # -- ** Searching with a predicate
376
+ # , find -- :: (a -> Bool) -> [a] -> Maybe a
377
+ # Implemented by Array
378
+
379
+ # , filter -- :: (a -> Bool) -> [a] -> [a]
380
+ def filter
381
+ warn "Method 'filter' is not implemented yet." if $VERBOSE
382
+ return []
383
+ end
384
+
385
+ # , partition -- :: (a -> Bool) -> [a] -> ([a], [a])
386
+ # Implemented by Array
387
+
388
+
389
+ # -- * Indexing lists
390
+ # -- | These functions treat a list @xs@ as a indexed collection,
391
+ # -- with indices ranging from 0 to @'length' xs - 1@.
392
+
393
+ # , (!!) -- :: [a] -> Int -> a
394
+ # Don't know how to implement it in Ruby
395
+
396
+
397
+ # , elemIndex -- :: (Eq a) => a -> [a] -> Maybe Int
398
+ def elem_index
399
+ warn "Method 'elem_index' is not implemented yet." if $VERBOSE
400
+ return []
401
+ end
402
+ alias elemIndex elem_index
403
+
404
+ # , elemIndices -- :: (Eq a) => a -> [a] -> [Int]
405
+ def elem_indices
406
+ warn "Method 'elem_indices' is not implemented yet." if $VERBOSE
407
+ return []
408
+ end
409
+ alias elemIndices elem_indices
410
+
411
+ # , findIndex -- :: (a -> Bool) -> [a] -> Maybe Int
412
+ def find_index
413
+ warn "Method 'find_index' is not implemented yet." if $VERBOSE
414
+ return []
415
+ end
416
+ alias findIndex find_index
417
+
418
+ # , findIndices -- :: (a -> Bool) -> [a] -> [Int]
419
+ def find_indices
420
+ warn "Method 'find_indices' is not implemented yet." if $VERBOSE
421
+ return []
422
+ end
423
+ alias findIndices find_indices
424
+
425
+
426
+ # -- * Zipping and unzipping lists
427
+
428
+ # , zip -- :: [a] -> [b] -> [(a,b)]
429
+ # Implemented by Array
430
+
431
+ # , zip3
432
+ def zip3
433
+ warn "Method 'zip3' is not implemented yet." if $VERBOSE
434
+ return []
435
+ end
436
+
437
+ # , zip4, zip5, zip6, zip7
438
+ def zip4
439
+ warn "Method 'zip4' is not implemented yet." if $VERBOSE
440
+ return []
441
+ end
442
+
443
+
444
+ # , zipWith -- :: (a -> b -> c) -> [a] -> [b] -> [c]
445
+ def zip_with
446
+ warn "Method 'zip_with' is not implemented yet." if $VERBOSE
447
+ return []
448
+ end
449
+ alias zipWith zip_with
450
+
451
+ # , zipWith3
452
+ def zip_with3
453
+ warn "Method 'zip_with3' is not implemented yet." if $VERBOSE
454
+ return []
455
+ end
456
+ alias zipWith3 zip_with3
457
+
458
+ # , zipWith4, zipWith5, zipWith6, zipWith7
459
+ def zip_with4
460
+ warn "Method 'zip_with4' is not implemented yet." if $VERBOSE
461
+ return []
462
+ end
463
+ alias zipWith4 zip_with4
464
+
465
+
466
+ # , unzip -- :: [(a,b)] -> ([a],[b])
467
+ def unzip
468
+ warn "Method 'unzip' is not implemented yet." if $VERBOSE
469
+ return []
470
+ end
471
+
472
+ # , unzip3
473
+ def unzip3
474
+ warn "Method 'unzip3' is not implemented yet." if $VERBOSE
475
+ return []
476
+ end
477
+
478
+ # , unzip4, unzip5, unzip6, unzip7
479
+ def unzip4
480
+ warn "Method 'unzip4' is not implemented yet." if $VERBOSE
481
+ return []
482
+ end
483
+
484
+
485
+ # -- * Special lists
486
+
487
+ # -- ** Functions on strings
488
+ # , lines -- :: String -> [String]
489
+ def lines
490
+ warn "Method 'lines' is not implemented yet." if $VERBOSE
491
+ return []
492
+ end
493
+
494
+ # , words -- :: String -> [String]
495
+ def words
496
+ warn "Method 'words' is not implemented yet." if $VERBOSE
497
+ return []
498
+ end
499
+
500
+ # , unlines -- :: [String] -> String
501
+ def unlines
502
+ warn "Method 'unlines' is not implemented yet." if $VERBOSE
503
+ return []
504
+ end
505
+
506
+ # , unwords -- :: [String] -> String
507
+ def unwords
508
+ warn "Method 'unwords' is not implemented yet." if $VERBOSE
509
+ return []
510
+ end
511
+
512
+
513
+ # -- ** \"Set\" operations
514
+
515
+ # , nub -- :: (Eq a) => [a] -> [a]
516
+ def nub
517
+ warn "Method 'nub' is not implemented yet." if $VERBOSE
518
+ return []
519
+ end
520
+
521
+
522
+ # , delete -- :: (Eq a) => a -> [a] -> [a]
523
+ # Implemented by Array but semantics is different
524
+ def delete(o)
525
+ warn "Method 'delete' is not implemented yet." if $VERBOSE
526
+ return []
527
+ end
528
+
529
+
530
+ # , (\\) -- :: (Eq a) => [a] -> [a] -> [a]
531
+ # Don't know how to implement it in Ruby
532
+
533
+
534
+ # , union -- :: (Eq a) => [a] -> [a] -> [a]
535
+ def union
536
+ warn "Method 'union' is not implemented yet." if $VERBOSE
537
+ return []
538
+ end
539
+
540
+ # , intersect -- :: (Eq a) => [a] -> [a] -> [a]
541
+ def intersect
542
+ warn "Method 'intersect' is not implemented yet." if $VERBOSE
543
+ return []
544
+ end
545
+
546
+
547
+ # -- ** Ordered lists
548
+ # , sort -- :: (Ord a) => [a] -> [a]
549
+ # Implemented by Array
550
+
551
+ # , insert -- :: (Ord a) => a -> [a] -> [a]
552
+ # Implemented by Array but semantics is different
553
+ def insert(o)
554
+ warn "Method 'insert' is not implemented yet." if $VERBOSE
555
+ return []
556
+ end
557
+
558
+
559
+ # def functional_fold(st, &op)
560
+ # f = proc { |s, a|
561
+ # if a.empty? then
562
+ # proc { s }
563
+ # else
564
+ # f.call(op.call(s, a[0]), a.slice(1, a.length-1))
565
+ # end
566
+ # }
567
+ # f.call(st, self)
568
+ # end
569
+
570
+ end # List
571
+
572
+ end # Prelude