Skip to content

Commit

Permalink
Merge branch 'release/0.9.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Przemyslaw Jan Pietrzak committed Jan 10, 2018
2 parents 8fa5498 + 478ac4a commit 8273b60
Show file tree
Hide file tree
Showing 29 changed files with 636 additions and 266 deletions.
2 changes: 0 additions & 2 deletions .coveragerc

This file was deleted.

1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
language: python
cache: pip
python:
- "3.4"
- "3.5"
Expand Down
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ With MIT licence. [Docs](http://pymonet.readthedocs.io/en/latest/?badge=latest)
### [Either](#either-1)
The Either type represents values with two possibilities: B value of type Either<A, B> is either Left<A> or Right. But not both in the same time.
### [Maybe](#maybe-1)
Maybe type is the most common way of representing nothingness (or the null type) with making the possibilities of NullPointer issues disappear.
Maybe is effectively abstract and has two concrete subtypes: Some (also Box) and None (also Nothing).
Maybe type is the most common way of representing nothingness (or the null type).
Maybe is effectively abstract and has two concrete subtypes: Box (also Some) and Nothing.
### [Box](#box-1)
Boxs are data-types that store values. No restriction is placed on how they store these values, though there may be restrictions on some methods if a Box is also an instance of a sub-class of Box.
### [Semigroups](#semigroups-1)
In mathematics, a semigroup is an algebraic structure consisting of a set together with an associative binary operation.
A semigroup generalizes a monoid in that there might not exist an identity element.
It also (originally) generalized a group (a monoid with all inverses) to a type where every element did not have to have an inverse, this the name semigroup.
### [Lazy](#lazy-1)
Lazy are data-types that store functions. Stored function will not be called until call of fold method
Lazy are data-types that store functions. Stored function will not be called until call of bind method
### [Task](#task-1)
Task are data-type for handle execution of functions (in lazy way) transform results of this function and handle errors.
### [Try](#try-1)
Expand All @@ -41,7 +41,7 @@ Set of functional programming helpers

## Either
The Either type represents values with two possibilities: B value of type Either<A, B> is either Left<A> or Right. But not both in the same time.
Left represents error value so any maps and fold will NOT be applied on it.
Left represents error value so any maps and bind will NOT be applied on it.

```python
from pymonet.either import Left, Right
Expand All @@ -60,13 +60,13 @@ def handle_success(value):

(divide(42, 0)
.map(lambda value: value + 1)
.fold(lambda value: Right(value + 1))
.bind(lambda value: Right(value + 1))
.case(error=handle_error, success=handle_success))
# error 42

(divide(42, 1)
.map(identity, lambda value: value + 1)
.fold(lambda value: Right(value + 1))
.bind(lambda value: Right(value + 1))
.case(error=handle_error, success=handle_success))
# success 44
```
Expand All @@ -91,20 +91,20 @@ get_index(1).get_or_else(0) # 3

```

Fold and map methods will be applied only when maybe is not empty
bind and map methods will be applied only when maybe is not empty
```python
from pymonet.Maybe import Maybe


get_index(42)\
.map(lambda value: value + 1)\
.fold(lambda value: Maybe.just(value + 1))\
.bind(lambda value: Maybe.just(value + 1))\
.get_or_else(0)
# 0

get_index(1)\
.map(lambda value: value + 1)\
.fold(lambda value: Maybe.just(value + 1))\
.bind(lambda value: Maybe.just(value + 1))\
.get_or_else(0)
# 3
```
Expand Down Expand Up @@ -140,7 +140,7 @@ box = Box(42) # Box<42>
.map(lambda value: value + 1) # Box<43>
.map(lambda value: str(value)) # Box<"43">
.map(lambda value: value[::-1]) # Box<"34">
.fold(lambda value: "output = " + value)) # "output = 34"
.bind(lambda value: "output = " + value)) # "output = 34"
```

## Semigroups
Expand Down Expand Up @@ -170,15 +170,15 @@ Sum(42).concat(Sum(1)) # Sum<43>
Sum(42).concat(Sum(1)).concat(Sum(1)) # Sum<44>
Sum(42).concat(Sum(1).concat(Sum(1))) # Sum<44>

Sum(42).fold(lambda value: value) # 42
Sum(42).bind(lambda value: value) # 42
```

#### First
```python
from pymonet.semigroups import First

First('first').concat(First('Second')) # First<"first">
First('first').fold(lambda value: value[::-1]) # "tsrif"
First('first').bind(lambda value: value[::-1]) # "tsrif"
```

#### Map
Expand All @@ -190,7 +190,7 @@ ingredient1.concat(ingredient2) # Map<{'score': Sum(3), 'won': All(True), 'capt
```

## Lazy
Lazy are data-types that store functions. Stored function will not be called until call of fold method
Lazy are data-types that store functions. Stored function will not be called until call of bind method
```python
from pymonet.lazy import Lazy

Expand All @@ -207,7 +207,7 @@ def side_effect(value):

lazy = Lazy(fn)
mapped_lazy = lazy.map(mapper)
mapped_lazy.fold(side_effect)
mapped_lazy.bind(side_effect)
# fn call
# mapper side effect of 42
# side effect of 42
Expand Down Expand Up @@ -239,22 +239,22 @@ def rejectable_fn(reject, resolve):
resolvable_task = Task.of(resolvable_fn)
rejectable_task = Task.of(rejectable_fn)
```
map method will be applied only on resolvable tasks during calling fold method
map method will be applied only on resolvable tasks during calling bind method
```python
resolvable_task.map(lambda value: value + 1) # Task<() -> 43>
rejectable_task.map(lambda value: value + 1) # Task<() -> 0>
```
fold method will be applied only on resolvable tasks. Fold also will call stored function
bind method will be applied only on resolvable tasks. bind also will call stored function
```python
def mapper(value):
print('mapper side effect ' + value)
return value + 1

resolvable_task.fold(mapper)
resolvable_task.bind(mapper)
# resolve side effect
# mapper side effect 42

rejectable_task.fold(mapper)
rejectable_task.bind(mapper)
# reject side effect
```

Expand Down
4 changes: 2 additions & 2 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
project = 'pyMonet'
copyright = '2017, Przemyslaw Jan Pietrzak'
author = 'Przemyslaw Jan Pietrzak'
version = '0.8.0'
release = '0.8.0'
version = '0.9.0'
release = '0.9.0'
language = None
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
pygments_style = 'sphinx'
Expand Down
2 changes: 1 addition & 1 deletion docs/box.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Box
.map(lambda value: value + 1) # Box<43>
.map(lambda value: str(value)) # Box<"43">
.map(lambda value: value[::-1]) # Box<"34">
.fold(lambda value: "output = " + value)) # "output = 34"
.bind(lambda value: "output = " + value)) # "output = 34"
.. autoclass:: pymonet.box.Box
:members: map, bind, ap, to_maybe, to_either, to_lazy, to_try, to_validation
4 changes: 2 additions & 2 deletions docs/either.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ Either
(divide(42, 0)
.map(lambda value: value + 1)
.fold(lambda value: Right(value + 1))
.bind(lambda value: Right(value + 1))
.case(error=handle_error, success=handle_success))
# error 42
(divide(42, 1)
.map(identity, lambda value: value + 1)
.fold(lambda value: Right(value + 1))
.bind(lambda value: Right(value + 1))
.case(error=handle_error, success=handle_success))
# success 44
Expand Down
2 changes: 1 addition & 1 deletion docs/lazy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ Lazy
# 42, 42
.. autoclass:: pymonet.lazy.Lazy
:members: __init__, __eq__, map, fold, get, to_validation
:members: __init__, __eq__, of, map, bind, get, to_validation
4 changes: 2 additions & 2 deletions docs/maybe.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ Maybe
get_index(42)\
.map(lambda value: value + 1)\
.fold(lambda value: Maybe.just(value + 1))\
.bind(lambda value: Maybe.just(value + 1))\
.get_or_else(0)
# 0
get_index(1)\
.map(lambda value: value + 1)\
.fold(lambda value: Maybe.just(value + 1))\
.bind(lambda value: Maybe.just(value + 1))\
.get_or_else(0)
get_index(42)\
Expand Down
10 changes: 5 additions & 5 deletions docs/task.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ Task
resolvable_task = Task.of(resolvable_fn)
rejectable_task = Task.of(rejectable_fn)
# map method will be applied only on resolvable tasks during calling fold method
# map method will be applied only on resolvable tasks during calling bind method
resolvable_task.map(lambda value: value + 1) # Task<() -> 43>
rejectable_task.map(lambda value: value + 1) # Task<() -> 0>
# fold method will be applied only on resolvable tasks. Fold also will call stored function
# bind method will be applied only on resolvable tasks. bind also will call stored function
def mapper(value):
print('mapper side effect ' + value)
return value + 1
resolvable_task.fold(mapper)
resolvable_task.bind(mapper)
# resolve side effect
# mapper side effect 42
rejectable_task.fold(mapper)
rejectable_task.bind(mapper)
# reject side effect
.. autoclass:: pymonet.task.Task
:members: __init__, of, reject, map, fold, to_validation
:members: __init__, of, reject, map, bind, to_validation
2 changes: 1 addition & 1 deletion docs/try.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ Try
.. autoclass:: pymonet.monad_try.Try
:members: of, map, fold, filter, get_or_else, get, on_success, on_fail
:members: of, map, bind, filter, get_or_else, get, on_success, on_fail
2 changes: 1 addition & 1 deletion index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ High abstract python library for functional programming. Contains algebraic data
./docs/lazy
./docs/try
./docs/task
./doc/validation
./docs/validation
./docs/utils
16 changes: 9 additions & 7 deletions pymonet/box.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ def __init__(self, value):
def __eq__(self, other):
return self.value == other.value

def __str__(self): # pragma: no cover
return 'Box[value={}]'.format(self.value)

def map(self, mapper):
"""
Take function (A) -> b and applied this function on current box value and returns new box with mapped value.
Expand All @@ -35,17 +38,16 @@ def bind(self, mapper):
"""
return mapper(self.value)

def ap(self, monad):
def ap(self, applicative):
"""
It takes as a parameter another Box type which contains a function,
and then applies that function to the value contained in the calling Box.
Applies the function inside the Box[A] structure to another applicative type.
:param monad: monad contains function
:type monad: Box[Function(A) -> B]
:param applicative: applicative contains function
:type applicative: Box[B]
:returns: new Box with result of contains function
:rtype: Box[B]
:rtype: Box[A(B)]
"""
return self.map(monad.value)
return applicative.map(self.value)

def to_maybe(self):
"""
Expand Down
15 changes: 7 additions & 8 deletions pymonet/either.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,16 @@ def case(self, error, success):
return success(self.value)
return error(self.value)

def ap(self, monad):
def ap(self, applicative):
"""
Take as a parameter another Box type which contains a function,
and then applies that function to the value contained in the calling Box.
Applies the function inside the Either[A] structure to another applicative type.
:param monad: monad contains function
:type monad: Box[Function(A) -> B]
:returns: new Box with result of contains function
:rtype: Box[B]
:param applicative: applicative contains function
:type applicative: Either[B]
:returns: new Either with result of contains function
:rtype: Either[A(B)]
"""
return self.map(monad.value)
return applicative.map(self.value)

def to_box(self):
"""
Expand Down
Loading

0 comments on commit 8273b60

Please sign in to comment.