prelude 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/CHANGELOG +25 -1
  2. data/README +11 -12
  3. data/Rakefile +6 -10
  4. data/lib/prelude.rb +36 -91
  5. data/lib/prelude/{tuple.rb → array_list.rb} +30 -27
  6. data/lib/prelude/functions.rb +414 -0
  7. data/lib/prelude/functors.rb +72 -0
  8. data/lib/prelude/lambda.rb +89 -0
  9. data/lib/prelude/minimal_array_list.rb +61 -0
  10. data/lib/prelude/monad.rb +11 -15
  11. data/lib/prelude/proper_list.rb +47 -0
  12. data/lib/prelude/proper_ruby_list.rb +48 -0
  13. data/lib/prelude/util.rb +33 -0
  14. data/test/tc_functions.rb +801 -0
  15. data/test/tc_monad.rb +21 -41
  16. data/test/ts_prelude.rb +2 -8
  17. metadata +13 -36
  18. data/doc/classes/Kernel.html +0 -198
  19. data/doc/classes/Prelude.html +0 -241
  20. data/doc/classes/Prelude/EmptyListError.html +0 -113
  21. data/doc/classes/Prelude/List.html +0 -2692
  22. data/doc/classes/Prelude/MissingFunctionError.html +0 -113
  23. data/doc/classes/Prelude/Monad.html +0 -283
  24. data/doc/classes/Prelude/Tuple.html +0 -217
  25. data/doc/classes/Proc.html +0 -198
  26. data/doc/classes/Symbol.html +0 -219
  27. data/doc/created.rid +0 -1
  28. data/doc/files/CHANGELOG.html +0 -122
  29. data/doc/files/README.html +0 -328
  30. data/doc/files/TODO.html +0 -95
  31. data/doc/files/lib/prelude/list_rb.html +0 -83
  32. data/doc/files/lib/prelude/monad_rb.html +0 -83
  33. data/doc/files/lib/prelude/tuple_rb.html +0 -83
  34. data/doc/files/lib/prelude_rb.html +0 -98
  35. data/doc/fr_class_index.html +0 -35
  36. data/doc/fr_file_index.html +0 -33
  37. data/doc/fr_method_index.html +0 -140
  38. data/doc/index.html +0 -27
  39. data/doc/rdoc-style.css +0 -208
  40. data/lib/prelude/list.rb +0 -588
  41. data/test/tc_higher.rb +0 -89
  42. data/test/tc_list.rb +0 -777
  43. data/test/tc_tuple.rb +0 -82
data/CHANGELOG CHANGED
@@ -1,6 +1,30 @@
1
1
  = CHANGELOG
2
2
 
3
- $Id: CHANGELOG 17 2006-09-17 18:03:15Z prelude $
3
+ $Id: CHANGELOG 34 2007-10-23 21:38:09Z prelude $
4
+
5
+ == 10/23/07 - Release 0.0.5
6
+ * Converted the implementation from function-based to constant-based, i.e., instead of
7
+
8
+ def and_(list)
9
+ foldr(lambda {|x,y| x && y}, true, list)
10
+ end
11
+
12
+ we define
13
+
14
+ AND = Lambda.new { |list|
15
+ FOLDR[BOOL_AND, true, list]
16
+ }
17
+
18
+ wich gives us an ability to do this
19
+
20
+ ALL = AND * MAP
21
+
22
+ instead of
23
+
24
+ def all(f, list)
25
+ and_(~map(f, list))
26
+ end
27
+
4
28
 
5
29
  == 09/17/06 - Release 0.0.3
6
30
  * Converted List from being functional-like to fully functional, i.e., all its methods return functions.
data/README CHANGED
@@ -1,9 +1,8 @@
1
1
  = Prelude - a Haskell-like functional library
2
2
 
3
- $Id: README 17 2006-09-17 18:03:15Z prelude $
3
+ $Id: README 34 2007-10-23 21:38:09Z prelude $
4
4
 
5
- *WARNING* <tt>The project is still in a very preliminary state. Only
6
- List was partially implemented. Feel free to contribute.</tt>
5
+ *WARNING* <tt>The project is still in a very preliminary state. Feel free to contribute.</tt>
7
6
 
8
7
  Project home is at http://rubyforge.org/projects/prelude/
9
8
 
@@ -29,10 +28,10 @@ a wish list, so treat it accordingly.
29
28
  === Rather curious collection of operations on lists
30
29
 
31
30
  Haskell's lists are different from Ruby's arrays in many ways. First
32
- of all, there are more operations defined on lists and the naming
33
- convention is different. Since Haskell's (or Lisp's) lists play a
34
- fundamental role in everything functional, their implementation seems
35
- necessary. Here are the goals for list's implementation:
31
+ of all, there are more operations defined on lists and, second, the
32
+ naming convention is different. Since Haskell's (or Lisp's) lists play
33
+ a fundamental role in everything functional, their implementation
34
+ seems necessary. Here are the goals for list's implementation:
36
35
 
37
36
  * Most, if not all, functions, i.e., +head+, +tail+, +last+, +first+, +concat+, etc.
38
37
 
@@ -66,8 +65,8 @@ While implementing majority of the Lambda world is relatively trivial
66
65
  in Ruby, some of the recursive beauty might be lost. Consider +foldl+,
67
66
  for example. The classic recursive definition like this
68
67
 
69
- def foldl(s, &block)
70
- empty? ? s : tail.foldl(block.call(s, head), &block)
68
+ def foldl(f, s, list)
69
+ list.empty? ? s : f(foldl(f, s, list.tail), list.head)
71
70
  end
72
71
 
73
72
  croaks on about 800+ elements integer lists, but more rubyish and
@@ -91,7 +90,7 @@ them. These need to be added to complete the picture:
91
90
 
92
91
  add5 = proc {|x| x+5}
93
92
  add6 = proc {|x| x+6}
94
- add11 = add5 << add6
93
+ add11 = add5 * add6
95
94
 
96
95
  I.e., the <tt>add5</tt> is an absolutely generic algorithm expressed
97
96
  in terms of other functions as long as <tt>add5</tt> takes as an
@@ -112,7 +111,7 @@ them. These need to be added to complete the picture:
112
111
  This is where all the previous trouble should start paying off
113
112
  allowing an application to be structured like this:
114
113
 
115
- result << connect << do_something << delete_something << with(params)
114
+ result >> connect >> do_something >> delete_something >> so_on
116
115
 
117
116
  Writing tutorials for monadic computations became a little industry in
118
117
  itself, see http://nomaware.com/monads/html/index.html to get
@@ -123,7 +122,7 @@ http://haskell.org/haskellwiki/Books_and_tutorials#Using_monads
123
122
 
124
123
  These features will be nice to have in a second release of the library:
125
124
 
126
- * General purpose monadic parser library similar to Parsec, see http://www.cs.uu.nl/~daan/parsec.html
125
+ * General purpose monadic parser library similar to Parsec, see http://www.cs.uu.nl/~daan/parsec.html or its Ruby port, see http://rubyforge.org/projects/rparsec/
127
126
 
128
127
  * Tools for automatic program verification and algebraic proofs
129
128
 
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # $Id: Rakefile 18 2006-09-17 23:33:58Z prelude $
2
+ # $Id: Rakefile 31 2006-12-28 02:28:28Z prelude $
3
3
  #
4
4
  # This file is part of the Prelude library that provides tools to
5
5
  # enable Haskell style functional programming in Ruby.
@@ -31,6 +31,7 @@
31
31
 
32
32
  require 'rubygems'
33
33
  require 'rake'
34
+ require 'rake/clean'
34
35
  require 'rake/testtask'
35
36
  require 'rake/rdoctask'
36
37
  require 'rake/packagetask'
@@ -46,11 +47,6 @@ PKG_VERSION = Prelude::VERSION
46
47
  PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
47
48
  PKG_DESTINATION = "../#{PKG_NAME}"
48
49
 
49
- RELEASE_NAME = "REL #{PKG_VERSION}"
50
-
51
- RUBY_FORGE_PROJECT = "prelude"
52
- RUBY_FORGE_USER = "prelude"
53
-
54
50
  desc "Default Task"
55
51
  task :default => [ :test ]
56
52
 
@@ -95,8 +91,8 @@ spec = Gem::Specification.new do |s|
95
91
  s.description = 'Enables Ruby programmers to use higher-order functions, monads, and other Haskell features.'
96
92
  s.author = 'Ivan K. and APP Design, Inc.'
97
93
  s.email = 'prelude@rubyforge.org'
98
- s.rubyforge_project = 'prelude'
99
- s.homepage = 'http://prelude.rubyforge.org'
94
+ s.rubyforge_project = PKG_NAME
95
+ s.homepage = "http://#{PKG_NAME}.rubyforge.org"
100
96
 
101
97
  s.has_rdoc = true
102
98
  s.requirements << 'none'
@@ -118,8 +114,8 @@ spec = Gem::Specification.new do |s|
118
114
  |x| x =~ /.*~/
119
115
  end
120
116
  end
121
- puts "Files included into the GEM:"
122
- pp s.files
117
+ puts "Files included into the GEM:" if $VERBOSE
118
+ pp s.files if $VERBOSE
123
119
 
124
120
  s.test_files = Dir.glob( "test/**/ts_*rb" )
125
121
  end
@@ -21,117 +21,62 @@
21
21
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
22
  #++
23
23
  #
24
- # $Id: prelude.rb 17 2006-09-17 18:03:15Z prelude $
24
+ # $Id: prelude.rb 34 2007-10-23 21:38:09Z prelude $
25
25
 
26
26
  $:.unshift(File.dirname(__FILE__))
27
27
 
28
+ require 'prelude/util'
29
+ require 'prelude/array_list'
30
+
31
+ # WARNING: Somehow rdoc breaks on multiline constants and does not
32
+ # generate a full list of constants below. Please see the sources for
33
+ # all defined functions and functors, there are plenty and they are all
34
+ # defined as constants.
35
+ #
36
+ # The implementation of frequently used functors is based on the code
37
+ # from Ben Yu's rparsec library, see http://rubyforge.org/frs/?group_id=2326
28
38
  module Prelude
29
39
 
30
- VERSION='0.0.3'
40
+ VERSION = '0.0.5'
31
41
 
32
- # Returns function that returns its argument
33
- Id = lambda { |x| x }
42
+ LIST_IMPLEMENTATION = Prelude::ArrayList
34
43
 
35
44
  # Thrown if an illegal operation is performed on an empty list.
36
45
  class EmptyListError < RuntimeError; end
37
46
 
38
- # This is used to handle empty list errors in this library. Re-define to fit.
39
- def empty_list_error
40
- raise EmptyListError, 'Illegal operation on an empty list.'
41
- end
47
+ # Thrown if a needed method is not available
48
+ class MissingMethodError < RuntimeError; end
42
49
 
43
50
  # Thrown if no function was supplied
44
51
  class MissingFunctionError < RuntimeError; end
45
52
 
46
- # This is used to handle missing function errors in this library. Re-define to fit.
47
- def missing_function_error
48
- raise MissingFunctionError, 'No function or block supplied.'
49
- end
50
-
51
- # A utility to determine if a function was passed
52
- def get_proc(f=nil, &block)
53
- # Has to be either function 'f' or block
54
- f = block_given? ? block : missing_function_error if f.nil?
55
- f.to_proc
56
- end
57
-
58
- end # Prelude
59
-
60
- class Symbol
61
-
62
- # Converts a symbol to a proc object
63
- def to_proc
64
- proc { |obj, *args| obj.send(self, *args) }
65
- end
66
-
67
- # Syntaxic sugar for something like this: -:+, i.e., defines proc object that executes 'plus'.
68
- alias -@ to_proc
69
-
70
- # FIXIT
71
- def curry(one, *args)
72
- proc { |*args| self.to_proc.call(one, *args) }
73
- end
74
-
75
- # This is will serve as an infix composition operator for symbols. If between two symbols,
76
- # returns composition proc, executes left symbol otherwise.
77
- def **(*args)
78
- if (1==args.length) && args[0].is_a?(Symbol)
79
- proc {|*a| self.to_proc.call(args[0].call(*a)) }
80
- else
81
- self.to_proc.call(*args.flatten)
82
- end
83
- end
84
- end # Symbol
53
+ # Thrown if something wrong with the functions' arguments
54
+ class ArgumentError < RuntimeError; end
85
55
 
86
- class Proc
56
+ # Thrown if bad list is encountered
57
+ class ImproperListError < RuntimeError; end
87
58
 
88
- # Syntaxic sugar for something like this: ~head(list), i.e., gives actual head instead of proc that
89
- # can do it if called.
90
- alias ~ call
91
-
92
- # FIXIT
93
- def curry(one, *args)
94
- lambda { |*args| self.call(one, *args)}
59
+ # A helper method to create an empty list of a given list type. Has to be a proper list.
60
+ def Prelude.new_list(list=nil)
61
+ res = LIST_IMPLEMENTATION.new(list)
62
+ #p "new_list #{res.inspect}"
63
+ raise ImproperListError unless res.kind_of?(Prelude::ProperList)
64
+ res
95
65
  end
96
66
 
97
- # This is will serve as an infix composition operator for procs. If between two procs,
98
- # returns composition proc, executes left proc otherwise.
99
- def **(*args)
100
- if (1==args.length) && args[0].is_a?(Proc)
101
- lambda {|*a| self.call(args[0].call(*a)) }
67
+ # A helper method to generate a new lambda that uses native implementation if available
68
+ def Prelude.use_native(meth)
69
+ list = Prelude.new_list
70
+ if list.kind_of?(Prelude::ProperList) and list.respond_to?(meth)
71
+ Lambda.new { |l, *args| l.method(meth)[*args] }
102
72
  else
103
- self.call(*args.flatten)
73
+ nil
104
74
  end
105
75
  end
106
76
 
107
- end # Proc
108
-
109
- module Kernel
110
-
111
- # Method object for currently executing method
112
- def this_method
113
- name = (Kernel.caller[0] =~ /`([^']*)'/ and $1)
114
- eval "self.method(\"#{name}\".to_sym)", binding
115
- end
116
-
117
- # Method object for the caller of the currently executing method
118
- def caller_method
119
- name = (Kernel.caller[1] =~ /`([^']*)'/ and $1)
120
- eval "self.method(\"#{name}\".to_sym)", binding
121
- end
122
-
123
- # Shuts up Ruby's warning.
124
- def silence_warnings
125
- old_verbose, $VERBOSE = $VERBOSE, nil
126
- yield
127
- ensure
128
- $VERBOSE = old_verbose
129
- end
130
-
131
- end # Kernel
77
+ end # Prelude
132
78
 
133
- silence_warnings do
134
- require 'prelude/list'
135
- require 'prelude/tuple'
136
- require 'prelude/monad'
137
- end
79
+ require 'prelude/lambda'
80
+ require 'prelude/functors'
81
+ require 'prelude/functions'
82
+ require 'prelude/monad'
@@ -21,40 +21,43 @@
21
21
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
22
  #++
23
23
 
24
+ require 'prelude/minimal_array_list'
25
+
24
26
  module Prelude
25
27
 
26
- # $Id: tuple.rb 7 2006-09-06 17:03:26Z prelude $
27
- #
28
- # The Tuple's being an Array should be considered an implementation inheritance.
29
- class Tuple < Array
30
-
31
- def initialize(*args)
32
- case
33
- when args.nil? || args.empty? :
34
- self[0] = self[1] = nil
35
- when args.length == 1 && args[0].kind_of?(Array) :
36
- self[0] = args[0][0]
37
- self[1] = args[0][1..-1]
38
- when args.length == 1 :
39
- self[0] = args[0]
40
- self[1] = nil
41
- when args.length == 2 :
42
- self[0] = args[0]
43
- self[1] = args[1]
44
- when args.length > 2 :
45
- self[0] = args[0]
46
- self[1] = args[1..-1]
47
- end # case
28
+ # $Id: array_list.rb 34 2007-10-23 21:38:09Z prelude $
29
+ #
30
+ # Implemenation of the minimal list functionality based on Ruby's arrays
31
+ class ArrayList < Prelude::MinimalArrayList
32
+
33
+ def initialize(a=nil)
34
+ #p "new #{a.inspect}"
35
+ @arr = []
36
+ a.each { |e| @arr << (e.kind_of?(Array) ? ArrayList.new(e) : e) } if a
37
+ self
38
+ end
39
+
40
+ def length
41
+ @arr.length
48
42
  end
49
43
 
50
- def fst
51
- self[0]
44
+ def append(list)
45
+ ArrayList.new(@arr+[*list])
52
46
  end
53
47
 
54
- def snd
55
- self[1]
48
+ def reverse
49
+ @arr.reverse
56
50
  end
57
51
 
58
- end # Tuple
52
+ def transpose
53
+ @arr.transpose
54
+ end
55
+
56
+ def to_a
57
+ res = []
58
+ @arr.each { |e| res << (e.kind_of?(ArrayList) ? e.to_a : e) }
59
+ res
60
+ end
59
61
 
62
+ end # ArrayList
60
63
  end # Prelude
@@ -0,0 +1,414 @@
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 library is free software; you can redistribute it and/or
10
+ # modify it under the terms of the GNU Lesser General Public
11
+ # License as published by the Free Software Foundation; either
12
+ # version 2.1 of the License, or (at your option) any later version.
13
+ #
14
+ # This library 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 GNU
17
+ # Lesser General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public
20
+ # License along with this library; if not, write to the Free Software
21
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
+ #++
23
+ # $Id: functions.rb 34 2007-10-23 21:38:09Z prelude $
24
+
25
+ module Prelude
26
+
27
+ # To handle error conditions
28
+ NOT_IMPLEMENTED_YET = Lambda.new { [] }
29
+
30
+ # (++)/append :: [a] -> [a] -> [a]
31
+ APPEND = Prelude.use_native(:append) || Lambda.new { |list1, list2|
32
+ #p "pp #{list1.inspect} #{list2.inspect}"
33
+
34
+ # Wrap non-list arguments.
35
+ list1 = new_list.cons(list1) unless list1.kind_of?(ProperList)
36
+ list2 = new_list.cons(list2) unless list2.kind_of?(ProperList)
37
+
38
+ case
39
+ when list1.null : list2
40
+ else APPEND[list1.tail, list2].cons(list1.head)
41
+ end
42
+ }
43
+
44
+ # last :: [a] -> a
45
+ LAST = Prelude.use_native(:last) || Lambda.new { |list|
46
+ case
47
+ when list.null : raise EmptyListError
48
+ when LENGTH[list] == 1 : list.head
49
+ else LAST[list.tail]
50
+ end
51
+ }
52
+
53
+ # init :: [a] -> [a]
54
+ INIT = Prelude.use_native(:init) || Lambda.new { |list|
55
+ case
56
+ when list.null : raise EmptyListError
57
+ when LENGTH[list] == 1 : new_list
58
+ else INIT[list.tail].cons(list.head)
59
+ end
60
+ }
61
+
62
+ # length :: [a] -> Int
63
+ LENGTH = Prelude.use_native(:length) || Lambda.new {|list|
64
+ case
65
+ when list.null : 0
66
+ else 1+LENGTH[list.tail]
67
+ end
68
+ }
69
+
70
+ # flip :: (a -> b -> c) -> b -> a -> c
71
+ FLIP = Lambda.new { |f, b, a|
72
+ #p "flip #{f.inspect} #{b.inspect} #{a.inspect}"
73
+ f[a, b]
74
+ }
75
+
76
+ # map :: (a -> b) -> [a] -> [b]
77
+ MAP = Lambda.new {|f, list|
78
+ #p "map #{f.inspect} #{list.inspect}"
79
+ case
80
+ when list.null : new_list
81
+ else MAP[f, list.tail].cons(f[list.head])
82
+ end
83
+ }
84
+
85
+ # reverse1 :: [a] -> [a]
86
+ REVERSE1 = Lambda.new { |list|
87
+ #p "reverse1 #{list.inspect}"
88
+ r = Lambda.new { |l, a|
89
+ #p "r #{l.inspect} #{a.inspect}"
90
+ case
91
+ when l.null : a
92
+ else r[l.tail, a.cons(l.head)]
93
+ end
94
+ }
95
+ r[list, new_list]
96
+ }
97
+
98
+ # reverse2 :: [a] -> [a]
99
+ REVERSE2 = Lambda.new { |list|
100
+ FOLDL[APPEND, new_list, list]
101
+ }
102
+
103
+ # reverse3 :: [a] -> [a]
104
+ REVERSE3 = Lambda.new { |list|
105
+ case
106
+ when list.null : new_list
107
+ else APPEND[REVERSE3[list.tail], new_list.cons(list.head)]
108
+ end
109
+ }
110
+
111
+ # reverse :: [a] -> [a]
112
+ REVERSE = Prelude.use_native(:reverse) || REVERSE1
113
+
114
+ # intersperse :: a -> [a] -> [a]
115
+ INTERSPERSE = Lambda.new { |a, list|
116
+ case
117
+ when list.null : new_list
118
+ when LENGTH[list] == 1 : list
119
+ else INTERSPERSE[a, list.tail].cons(a).cons(list.head)
120
+ end
121
+ }
122
+
123
+ # transpose :: [[a]] -> [[a]]
124
+ TRANSPOSE = Prelude.use_native(:transpose) || Lambda.new { |list|
125
+ # FIXIT
126
+ list.transpose
127
+ }
128
+
129
+ # # * Reducing lists (folds)
130
+
131
+ # foldl :: (a -> b -> a) -> a -> [b] -> a
132
+ FOLDL = Lambda.new { |f, s, list|
133
+ #p "foldl #{f.inspect} #{s.inspect} #{list.inspect}"
134
+ case
135
+ when list.null : s
136
+ else f[FOLDL[f, s, list.tail], list.head]
137
+ end
138
+ }
139
+
140
+ # foldl' :: (a -> b -> a) -> a -> [b] -> a
141
+ FOLDL_ = Lambda.new { |f, s, list|
142
+ warn "Method 'foldl_' is not implemented yet." if $VERBOSE
143
+ NOT_IMPLEMENTED_YET
144
+ }
145
+
146
+ # foldl1 :: (a -> a -> a) -> [a] -> a
147
+ FOLDL1 = Lambda.new { |f, list|
148
+ FOLDL[f, list.head, list.tail]
149
+ }
150
+
151
+ # foldl1' :: (a -> a -> a) -> [a] -> a
152
+ FOLDL1_ = Lambda.new { |f, list|
153
+ warn "Method 'foldl1_' is not implemented yet." if $VERBOSE
154
+ NOT_IMPLEMENTED_YET
155
+ }
156
+
157
+ # foldr :: (a -> b -> b) -> b -> [a] -> b
158
+ FOLDR = Lambda.new { |f, s, list|
159
+ #p "foldr #{f.inspect} #{s.inspect} #{list.inspect}"
160
+ case
161
+ when list.null : s
162
+ else f[list.head, FOLDR[f, s, list.tail]]
163
+ end
164
+ }
165
+
166
+ # foldr1 :: (a -> a -> a) -> [a] -> a
167
+ FOLDR1 = Lambda.new { |f, list|
168
+ FOLDR[f, list.head, list.tail]
169
+ }
170
+
171
+ # ** Special folds
172
+
173
+ # concat :: [[a]] -> [a]
174
+ CONCAT = Lambda.new { |list|
175
+ FOLDR[APPEND, new_list, list]
176
+ }
177
+
178
+ # concatMap :: (a -> [b]) -> [a] -> [b]
179
+ CONCAT_MAP = Lambda.new { |f, list|
180
+ FOLDR[APPEND * f, new_list, list]
181
+ }
182
+
183
+ # and :: [Bool] -> Bool
184
+ AND = Lambda.new { |list|
185
+ FOLDR[BOOL_AND, true, list]
186
+ }
187
+
188
+ # or :: [Bool] -> Bool
189
+ OR = Lambda.new { |list|
190
+ FOLDR[BOOL_OR, false, list]
191
+ }
192
+
193
+ # any :: (a -> Bool) -> [a] -> Bool
194
+ ANY = OR * MAP
195
+
196
+ # all :: (a -> Bool) -> [a] -> Bool
197
+ ALL = AND * MAP
198
+
199
+ # sum :: (Num a) => [a] -> a
200
+ SUM = NOT_IMPLEMENTED_YET
201
+
202
+ # product :: (Num a) => [a] -> a
203
+ PRODUCT = NOT_IMPLEMENTED_YET
204
+
205
+ # maximum :: (Ord a) => [a] -> a
206
+ MAXIMUM = NOT_IMPLEMENTED_YET
207
+
208
+ # minimum :: (Ord a) => [a] -> a
209
+ MINIMUM = NOT_IMPLEMENTED_YET
210
+
211
+ # * Building lists
212
+
213
+ # ** Scans
214
+
215
+ # scanl :: (a -> b -> a) -> a -> [b] -> [a]
216
+ SCANL = NOT_IMPLEMENTED_YET
217
+
218
+ # scanl1 :: (a -> a -> a) -> [a] -> [a]
219
+ SCANL1 = NOT_IMPLEMENTED_YET
220
+
221
+ # scanr :: (a -> b -> b) -> b -> [a] -> [b]
222
+ SCANR = NOT_IMPLEMENTED_YET
223
+
224
+ # scanr1 :: (a -> a -> a) -> [a] -> [a]
225
+ SCANR1 = NOT_IMPLEMENTED_YET
226
+
227
+ # ** Accumulating maps
228
+
229
+ # mapAccumL :: (a -> b -> (a,c)) -> a -> [b] -> (a,[c])
230
+ MAP_ACCUM_L = NOT_IMPLEMENTED_YET
231
+
232
+ # mapAccumR :: (a -> b -> (a,c)) -> a -> [b] -> (a,[c])
233
+ MAP_ACCUM_R = NOT_IMPLEMENTED_YET
234
+
235
+ # ** Infinite lists
236
+
237
+ # iterate :: (a -> a) -> a -> [a]
238
+ ITERATE = NOT_IMPLEMENTED_YET
239
+
240
+ # repeat :: a -> [a]
241
+ REPEAT = NOT_IMPLEMENTED_YET
242
+
243
+ # replicate :: Int -> a -> [a]
244
+ REPLICATE = NOT_IMPLEMENTED_YET
245
+
246
+ # cycle :: [a] -> [a]
247
+ CYCLE = NOT_IMPLEMENTED_YET
248
+
249
+ # ** Unfolding
250
+
251
+ # unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
252
+ UNFOLDR = NOT_IMPLEMENTED_YET
253
+
254
+ # * Sublists
255
+
256
+ # ** Extracting sublists
257
+
258
+ # take :: Int -> [a] -> [a]
259
+ TAKE = NOT_IMPLEMENTED_YET
260
+
261
+ # drop :: Int -> [a] -> [a]
262
+ DROP = NOT_IMPLEMENTED_YET
263
+
264
+ # splitAt :: Int -> [a] -> ([a], [a])
265
+ SPLIT_AT = NOT_IMPLEMENTED_YET
266
+
267
+ # takeWhile :: (a -> Bool) -> [a] -> [a]
268
+ TAKE_WHILE = NOT_IMPLEMENTED_YET
269
+
270
+ # dropWhile :: (a -> Bool) -> [a] -> [a]
271
+ DROP_WHILE = NOT_IMPLEMENTED_YET
272
+
273
+ # span :: (a -> Bool) -> [a] -> ([a], [a])
274
+ SPAN = NOT_IMPLEMENTED_YET
275
+
276
+ # break :: (a -> Bool) -> [a] -> ([a], [a])
277
+ BREAK_ = NOT_IMPLEMENTED_YET
278
+
279
+ # group :: Eq a => [a] -> [[a]]
280
+ GROUP = NOT_IMPLEMENTED_YET
281
+
282
+ # inits :: [a] -> [[a]]
283
+ INITS = NOT_IMPLEMENTED_YET
284
+
285
+ # tails :: [a] -> [[a]]
286
+ TAILS = NOT_IMPLEMENTED_YET
287
+
288
+ # ** Predicates
289
+
290
+ # isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
291
+ IS_PREFIX_OF = NOT_IMPLEMENTED_YET
292
+
293
+ # isSuffixOf :: (Eq a) => [a] -> [a] -> Bool
294
+ IS_SUFFIX_OF = NOT_IMPLEMENTED_YET
295
+
296
+ # * Searching lists
297
+
298
+ # ** Searching by equality
299
+
300
+ # elem :: a -> [a] -> Bool
301
+ ELEM = NOT_IMPLEMENTED_YET
302
+
303
+ # notElem :: a -> [a] -> Bool
304
+ NOT_ELEM = NOT_IMPLEMENTED_YET
305
+
306
+ # lookup :: (Eq a) => a -> [(a,b)] -> Maybe b
307
+ LOOKUP = NOT_IMPLEMENTED_YET
308
+
309
+ # ** Searching with a predicate
310
+
311
+ # find :: (a -> Bool) -> [a] -> Maybe a
312
+ FIND = NOT_IMPLEMENTED_YET
313
+
314
+ # filter :: (a -> Bool) -> [a] -> [a]
315
+ FILTER = NOT_IMPLEMENTED_YET
316
+
317
+ # partition :: (a -> Bool) -> [a] -> ([a], [a])
318
+ PARTITION = NOT_IMPLEMENTED_YET
319
+
320
+ # * Indexing lists
321
+
322
+ # | These functions treat a list @xs@ as a indexed collection,
323
+ # with indices ranging from 0 to @'length' xs - 1@.
324
+
325
+
326
+ # elemIndex :: (Eq a) => a -> [a] -> Maybe Int
327
+ ELEM_INDEX = NOT_IMPLEMENTED_YET
328
+
329
+ # elemIndices :: (Eq a) => a -> [a] -> [Int]
330
+ ELEM_INDICES = NOT_IMPLEMENTED_YET
331
+
332
+ # findIndex :: (a -> Bool) -> [a] -> Maybe Int
333
+ FIND_INDEX = NOT_IMPLEMENTED_YET
334
+
335
+ # findIndices :: (a -> Bool) -> [a] -> [Int]
336
+ FIND_INDICES = NOT_IMPLEMENTED_YET
337
+
338
+ # * Zipping and unzipping lists
339
+
340
+ # zip :: [a] -> [b] -> [(a,b)]
341
+ ZIP = Lambda.new { |list1, list2|
342
+ #p "zip #{list1.inspect} #{list2.inspect}"
343
+ case
344
+ when (list1.null or list2.null) : []
345
+ when (LENGTH[list1] == 1 or LENGTH[list2] == 1) :
346
+ new_list.cons(new_list.cons(list2.head).cons(list1.head))
347
+ else
348
+ ZIP[list1.tail, list2.tail].cons(new_list.cons(list2.head).cons(list1.head))
349
+ end
350
+ }
351
+
352
+ # zip3
353
+ ZIP3 = NOT_IMPLEMENTED_YET
354
+
355
+ # zip4, zip5, zip6, zip7
356
+ ZIP4 = NOT_IMPLEMENTED_YET
357
+
358
+ # zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
359
+ ZIP_WITH = NOT_IMPLEMENTED_YET
360
+
361
+ # zipWith3
362
+ ZIP_WITH3 = NOT_IMPLEMENTED_YET
363
+
364
+ # zipWith4, zipWith5, zipWith6, zipWith7
365
+ ZIP_WITH4 = NOT_IMPLEMENTED_YET
366
+
367
+ # unzip :: [(a,b)] -> ([a],[b])
368
+ UNZIP = NOT_IMPLEMENTED_YET
369
+
370
+ # unzip3
371
+ UNZIP3 = NOT_IMPLEMENTED_YET
372
+
373
+ # unzip4, unzip5, unzip6, unzip7
374
+ UNZIP4 = NOT_IMPLEMENTED_YET
375
+
376
+ # * Special lists
377
+
378
+ # ** Functions on strings
379
+
380
+ # lines :: String -> [String]
381
+ LINES = NOT_IMPLEMENTED_YET
382
+
383
+ # words :: String -> [String]
384
+ WORDS = NOT_IMPLEMENTED_YET
385
+
386
+ # unlines :: [String] -> String
387
+ UNLINES = NOT_IMPLEMENTED_YET
388
+
389
+ # unwords :: [String] -> String
390
+ UNWORDS = NOT_IMPLEMENTED_YET
391
+
392
+ # ** "Set" operations
393
+
394
+ # nub :: (Eq a) => [a] -> [a]
395
+ NUB = NOT_IMPLEMENTED_YET
396
+
397
+ # delete :: (Eq a) => a -> [a] -> [a]
398
+ DELETE = NOT_IMPLEMENTED_YET
399
+
400
+ # union :: (Eq a) => [a] -> [a] -> [a]
401
+ UNION = NOT_IMPLEMENTED_YET
402
+
403
+ # intersect :: (Eq a) => [a] -> [a] -> [a]
404
+ INTERSECT = NOT_IMPLEMENTED_YET
405
+
406
+ # ** Ordered lists
407
+
408
+ # sort :: (Ord a) => [a] -> [a]
409
+ SORT = NOT_IMPLEMENTED_YET
410
+
411
+ # insert :: (Ord a) => a -> [a] -> [a]
412
+ INSERT = NOT_IMPLEMENTED_YET
413
+
414
+ end # Prelude