prelude 0.0.3 → 0.0.5

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.
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