kleisli 0.2.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 997aca6d77f858cf9262df7edbc913179cd8004f
4
- data.tar.gz: dac24d37b400e98703e6299fb6a702ea5df773eb
5
- SHA512:
6
- metadata.gz: 009f9357a66c1003610f90cd86e734c00632efa6b8b511d5eec2bdc91daceb41bc3f1ebf667615065aefd506435510f8de97a83518a2e6259241f649224d0fef
7
- data.tar.gz: 77f136e1fb92e6d315c7b423aa2c5e8f32b3f3f1f2ec0071488c51557cab9d52d51a3d6b1f105211f2525979825456a4ea09ea53aa78d6e0b2809ffa581f9ec7
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0edc56dbf5e93057c443c0957b312524b8d20d7d
4
+ data.tar.gz: dee2ed0829f1ad9c4ad19f15a8f86293a79e2363
5
+ SHA512:
6
+ metadata.gz: 890887f61bd1b551028fea3384da9654e5394fa4da1ee993d3bf77ac5f43befe3b7ec64cd28002178dc933952cf0ecc638c694c37a88d87a64bcfeddfed1d068
7
+ data.tar.gz: 513db7d077f6061c734c6cde0fa7ccee7ba94e64b8b5195cce1d49642311ec4360c96dffba20cd44ef86b914d5aae0ae1461a86bf42e85fdbb12f8042873a623
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Kleisli [![Build Status](https://secure.travis-ci.org/txus/adts.png)](http://travis-ci.org/txus/adts)
1
+ # Kleisli [![Build Status](https://secure.travis-ci.org/txus/kleisli.png)](http://travis-ci.org/txus/kleisli)
2
2
 
3
3
  An idiomatic, clean implementation of a few common useful monads in Ruby,
4
4
  written by [Ryan Levick][rylev] and me.
@@ -68,7 +68,7 @@ f.call " localhost:9092 "
68
68
 
69
69
  # Partially applied lambda:
70
70
  my_split = lambda { |str, *args| str.split(*args) }
71
- f = F . fn(":", &split)
71
+ f = F . fn(":", &my_split) . strip
72
72
  f.call " localhost:9092 "
73
73
  # => ["localhost", "9092"]
74
74
  ```
@@ -261,7 +261,7 @@ require "kleisli"
261
261
 
262
262
  add = -> x, y { x + y }
263
263
  Right(add) * Right(10) * Right(2)
264
- # => Some(12)
264
+ # => Right(12)
265
265
  Right(add) * Left("error") * Right(2)
266
266
  # => Left("error")
267
267
  ```
@@ -298,46 +298,6 @@ result # => Some(10)
298
298
  result # => None()
299
299
  ```
300
300
 
301
- ## Writer
302
-
303
- The Writer monad is arguably the least useful monad in Ruby (as side effects
304
- are uncontrolled), but let's take a look at it anyway.
305
-
306
- It is used to model computations that *append* to some kind of state (which
307
- needs to be a Monoid, expressed in the `Kleisli::Monoid` mixin) at each step.
308
-
309
- (We've already implemented the Monoid interface for `String`, `Array`, `Hash`,
310
- `Fixnum` and `Float` for you.)
311
-
312
- An example would be a pipeline of computations that append to a log, for
313
- example a list of strings.
314
-
315
- ### `>->` (bind)
316
-
317
- ```ruby
318
- require "kleisli"
319
-
320
- writer = Writer([], 100) >-> value {
321
- Writer(["added 100"], value + 100)
322
- } >-> value {
323
- Writer(["added 140 more"], value + 140)
324
- } # => Writer(["added 100", "added 140 more"], 340)
325
-
326
- log, value = writer.unwrap
327
- log # => ["added 100", "added 140 more"]
328
- value # => 340
329
- ```
330
-
331
- ### `fmap`
332
-
333
- ```ruby
334
- require "kleisli"
335
-
336
- writer = Writer([], 100).fmap { |value|
337
- value + 100
338
- } # => Writer([], 200)
339
- ```
340
-
341
301
  ## Future
342
302
 
343
303
  The Future monad models a pipeline of computations that will happen in the future, as soon as the value needed for each step is available. It is useful to model, for example, a sequential chain of HTTP calls.
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require "rake/testtask"
3
3
 
4
4
  Rake::TestTask.new do |t|
5
5
  t.libs << "test"
6
- t.test_files = FileList['test/**/*.rb']
6
+ t.test_files = FileList['test/**/*_test.rb']
7
7
  t.verbose = true
8
8
  end
9
9
 
data/kleisli.gemspec CHANGED
@@ -20,4 +20,5 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.6"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "minitest", "~> 5.5"
23
24
  end
data/lib/kleisli.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require "kleisli/version"
2
2
  require "kleisli/maybe"
3
3
  require "kleisli/try"
4
- require "kleisli/writer"
5
4
  require "kleisli/future"
6
5
  require "kleisli/either"
7
6
  require "kleisli/composition"
data/lib/kleisli/blank.rb CHANGED
@@ -24,7 +24,7 @@ class Blank
24
24
  def hide(name)
25
25
  methods = instance_methods.map(&:to_sym)
26
26
  if methods.include?(name.to_sym) and
27
- name !~ /^(__|instance_eval)/
27
+ name !~ /^(__|instance_eval|object_id)/
28
28
  @hidden_methods ||= {}
29
29
  @hidden_methods[name.to_sym] = instance_method(name)
30
30
  undef_method name
@@ -1,18 +1,10 @@
1
1
  require_relative 'blank'
2
2
 
3
- class Proc
4
- def self.comp(f, g)
5
- lambda { |*args| f[g[*args]] }
6
- end
7
-
8
- def *(g)
9
- Proc.comp(self, g)
10
- end
11
- end
12
-
13
3
  module Kleisli
14
4
  class ComposedFn < Blank
15
- include ::Kernel
5
+ def self.comp(f, g)
6
+ lambda { |*args| f[g[*args]] }
7
+ end
16
8
 
17
9
  def initialize(fns=[])
18
10
  @fns = fns
@@ -34,7 +26,7 @@ module Kleisli
34
26
 
35
27
  def call(*args)
36
28
  if @fns.any?
37
- @fns.reduce(:*).call(*args)
29
+ @fns.reduce { |f, g| ComposedFn.comp(f, g) }.call(*args)
38
30
  else
39
31
  args.first
40
32
  end
@@ -1,3 +1,3 @@
1
1
  module Kleisli
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class CompositionTest < MiniTest::Unit::TestCase
3
+ class CompositionTest < Minitest::Test
4
4
  def test_one_method
5
5
  f = F . first
6
6
  result = f.call([1])
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class EitherTest < MiniTest::Unit::TestCase
3
+ class EitherTest < Minitest::Test
4
4
  def test_lift_right
5
5
  assert_equal 3, Right(3).value
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class FutureTest < MiniTest::Unit::TestCase
3
+ class FutureTest < Minitest::Test
4
4
  def test_immediate_value
5
5
  assert_equal 30, Future(30).await
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class MaybeTest < MiniTest::Unit::TestCase
3
+ class MaybeTest < Minitest::Test
4
4
  def test_unwrapping_some
5
5
  assert_equal 3, Some(3).value
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class TryTest < MiniTest::Unit::TestCase
3
+ class TryTest < Minitest::Test
4
4
  def test_success
5
5
  assert_equal 2, Try { 10 / 5 }.value
6
6
  end
data/test/test_helper.rb CHANGED
@@ -1,2 +1,3 @@
1
1
  require 'kleisli'
2
- require 'test/unit'
2
+ require 'minitest'
3
+ require 'minitest/autorun'
metadata CHANGED
@@ -1,61 +1,66 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: kleisli
3
- version: !ruby/object:Gem::Version
4
- version: 0.2.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - Josep M. Bach
8
8
  - Ryan Levick
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-11-22 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
12
+
13
+ date: 2014-12-18 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
15
16
  name: bundler
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: '1.6'
21
- type: :development
22
17
  prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - "~>"
26
- - !ruby/object:Gem::Version
27
- version: '1.6'
28
- - !ruby/object:Gem::Dependency
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: "1.6"
23
+ type: :development
24
+ version_requirements: *id001
25
+ - !ruby/object:Gem::Dependency
29
26
  name: rake
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - "~>"
33
- - !ruby/object:Gem::Version
34
- version: '10.0'
27
+ prerelease: false
28
+ requirement: &id002 !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: "10.0"
35
33
  type: :development
34
+ version_requirements: *id002
35
+ - !ruby/object:Gem::Dependency
36
+ name: minitest
36
37
  prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - "~>"
40
- - !ruby/object:Gem::Version
41
- version: '10.0'
38
+ requirement: &id003 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ version: "5.5"
43
+ type: :development
44
+ version_requirements: *id003
42
45
  description: Usable, idiomatic common monads in Ruby
43
- email:
46
+ email:
44
47
  - josep.m.bach@gmail.com
45
48
  - ryan.levick@gmail.com
46
49
  executables: []
50
+
47
51
  extensions: []
52
+
48
53
  extra_rdoc_files: []
49
- files:
50
- - ".gitignore"
51
- - ".travis.yml"
54
+
55
+ files:
56
+ - .gitignore
57
+ - .travis.yml
52
58
  - Gemfile
53
59
  - LICENSE.txt
54
60
  - README.md
55
61
  - Rakefile
56
62
  - kleisli.gemspec
57
63
  - lib/kleisli.rb
58
- - lib/kleisli/applicative_functor.rb
59
64
  - lib/kleisli/blank.rb
60
65
  - lib/kleisli/composition.rb
61
66
  - lib/kleisli/either.rb
@@ -63,48 +68,44 @@ files:
63
68
  - lib/kleisli/future.rb
64
69
  - lib/kleisli/maybe.rb
65
70
  - lib/kleisli/monad.rb
66
- - lib/kleisli/monoid.rb
67
71
  - lib/kleisli/try.rb
68
72
  - lib/kleisli/version.rb
69
- - lib/kleisli/writer.rb
70
73
  - test/kleisli/composition_test.rb
71
74
  - test/kleisli/either_test.rb
72
75
  - test/kleisli/future_test.rb
73
76
  - test/kleisli/maybe_test.rb
74
- - test/kleisli/monoid_test.rb
75
77
  - test/kleisli/try_test.rb
76
- - test/kleisli/writer_test.rb
77
78
  - test/test_helper.rb
78
79
  homepage: https://github.com/txus/kleisli
79
- licenses:
80
+ licenses:
80
81
  - MIT
81
82
  metadata: {}
83
+
82
84
  post_install_message:
83
85
  rdoc_options: []
84
- require_paths:
86
+
87
+ require_paths:
85
88
  - lib
86
- required_ruby_version: !ruby/object:Gem::Requirement
87
- requirements:
88
- - - ">="
89
- - !ruby/object:Gem::Version
90
- version: '0'
91
- required_rubygems_version: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
95
- version: '0'
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - &id004
92
+ - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - *id004
96
98
  requirements: []
99
+
97
100
  rubyforge_project:
98
- rubygems_version: 2.2.2
101
+ rubygems_version: 2.4.4
99
102
  signing_key:
100
103
  specification_version: 4
101
104
  summary: Usable, idiomatic common monads in Ruby
102
- test_files:
105
+ test_files:
103
106
  - test/kleisli/composition_test.rb
104
107
  - test/kleisli/either_test.rb
105
108
  - test/kleisli/future_test.rb
106
109
  - test/kleisli/maybe_test.rb
107
- - test/kleisli/monoid_test.rb
108
110
  - test/kleisli/try_test.rb
109
- - test/kleisli/writer_test.rb
110
111
  - test/test_helper.rb
@@ -1,4 +0,0 @@
1
- module Kleisli
2
- class ApplicativeFunctor < Functor
3
- end
4
- end
@@ -1,65 +0,0 @@
1
- module Kleisli
2
- module Monoid
3
- def fold(others)
4
- others.reduce(self) { |acc, x| acc.mappend x }
5
- end
6
-
7
- def mempty
8
- raise NotImplementedError, "this monoid doesn't implement mpemty"
9
- end
10
-
11
- def mappend(other)
12
- raise NotImplementedError, "this monoid doesn't implement mappend"
13
- end
14
- end
15
- end
16
-
17
- String.class_eval do
18
- include Kleisli::Monoid
19
-
20
- def mempty
21
- ""
22
- end
23
-
24
- alias mappend +
25
- end
26
-
27
- Array.class_eval do
28
- include Kleisli::Monoid
29
-
30
- def mempty
31
- []
32
- end
33
-
34
- alias mappend +
35
- end
36
-
37
- Hash.class_eval do
38
- include Kleisli::Monoid
39
-
40
- def mempty
41
- {}
42
- end
43
-
44
- alias mappend merge
45
- end
46
-
47
- Fixnum.class_eval do
48
- include Kleisli::Monoid
49
-
50
- def mempty
51
- 0
52
- end
53
-
54
- alias mappend +
55
- end
56
-
57
- Float.class_eval do
58
- include Kleisli::Monoid
59
-
60
- def mempty
61
- 0
62
- end
63
-
64
- alias mappend +
65
- end
@@ -1,36 +0,0 @@
1
- require 'kleisli/monad'
2
- require 'kleisli/monoid'
3
-
4
- module Kleisli
5
- class Writer < Monad
6
- def self.lift(log, value)
7
- new(log, value)
8
- end
9
-
10
- def initialize(log, value)
11
- @log, @value = log, value
12
- end
13
-
14
- def ==(other)
15
- unwrap == other.unwrap
16
- end
17
-
18
- def >(f)
19
- other_log, other_value = f.call(@value).unwrap
20
- Writer.new(@log + other_log, other_value)
21
- end
22
-
23
- def fmap(&f)
24
- new_value = f.call(@value)
25
- Writer.new(@log, new_value)
26
- end
27
-
28
- def unwrap
29
- [@log, @value]
30
- end
31
- end
32
- end
33
-
34
- def Writer(log, value)
35
- Kleisli::Writer.lift(log, value)
36
- end
@@ -1,23 +0,0 @@
1
- require 'test_helper'
2
-
3
- class MonoidTest < MiniTest::Unit::TestCase
4
- def test_string_fold
5
- assert_equal "hellogoodbye", "hello".fold(%w(good bye))
6
- end
7
-
8
- def test_array_fold
9
- assert_equal [1, 2, 3], [1].fold([[2], [3]])
10
- end
11
-
12
- def test_hash_fold
13
- assert_equal({a: 1, b: 2, c: 3}, {a: 1}.fold([{b: 2}, {c: 3}]))
14
- end
15
-
16
- def test_fixnum_fold
17
- assert_equal 6, 1.fold([2,3])
18
- end
19
-
20
- def test_float_fold
21
- assert_equal 6.0, 1.0.fold([2.0,3.0])
22
- end
23
- end
@@ -1,19 +0,0 @@
1
- require 'test_helper'
2
-
3
- class WriterTest < MiniTest::Unit::TestCase
4
- def test_unwrap
5
- log, value = Writer("log", 100).unwrap
6
- assert_equal "log", log
7
- assert_equal 100, value
8
- end
9
-
10
- def test_bind
11
- writer = Writer("foo", 100) >-> value { Writer("bar", value + 100) }
12
- assert_equal Writer("foobar", 200), writer
13
- end
14
-
15
- def test_fmap
16
- writer = Writer("foo", 100).fmap { |value| value + 100 }
17
- assert_equal Writer("foo", 200), writer
18
- end
19
- end