haskpy.types.dictionary.Dictionary

Dictionary

class Dictionary(*args, **kwargs)[source]

Bases: Apply, Eq, Monoid, Traversable

Dictionary type

__add__(other)

Append two monoids

Using + operator to append two monoid values seems natural because that’s what Python is doing by default because lists are concatenated with +.

__annotations__ = {}
__attrs_init__(Dictionary__dict) None

Method generated by attrs for class Dictionary.

__contains__(x)

Override elem if you want to change the default implementation

__eq__(other)[source]

Mark method non-existing

This is a workaround for Python forcefully creating some methods. One cannot create objects that don’t have __eq__, __ge__, __gt__ and many other methods. They are there and it’s not possible to delete them. With this wrapper you can override those methods so that they won’t show up in __dir__ listing and if accessed in any way, AttributeError is raised. Note that it just hides the methods, one can still access them as object.__getattribute__(obj, "__eq__").

__eq_test__(other, data=None)[source]
__getitem__(key)[source]
__hash__ = None
__iter__()

Override to_iter if you want to change the default implementation

__len__()

Override length if you want to change the default implementation

__lshift__(x)

Sequence with << similarly as with <* and << in Haskell

__matmul__(x)

Application operand @ applies similarly as <*> in Haskell

f @ x translates to f.apply_to(x), x.apply(f) and apply(f, x).

Why @ operator?

  • It’s not typically used as often as some other more common operators so less risk for confusion.

  • The operator is not a commutative as isn’t apply either.

  • If we see matrix as some structure, then matrix multiplication takes both left and right operand inside this structure and gives a result also inside this structure, similarly as apply does. So it’s an operator for two operands having a similar structure.

  • The operator evaluates the contained function(s) at the contained value(s). Thus, f “at” x makes perfect sense.

__ne__(other)

Inequality comparison: Eq a => a -> a -> bool

Can be used as != operator.

The default implementation uses __eq__.

__rpow__(f)

Lifting operator ** lifts similarly as <$> in Haskell

f ** x translates to x.map(f) and map(f, x).

Why ** operator?

  • It’s not typically used as often as multiplication or addition so less risk of confusion.

  • It’s not commutative operator as isn’t lifting either.

  • The two operands have very different roles. They are not at the same “level”.

  • The right operand is “higher”, that is, it’s inside a structure and the left operand is kind of “raised to the power” of the second operand, where the “power” is the functorial structure.

  • The same operand is also used for function composition because function composition is just mapping. Visually the symbol can be seen as chaining two stars similarly as function composition chains two functions.

__rshift__(x)

Sequence with >> similarly as with *> and >> in Haskell

alter(f, key)[source]
append(other)[source]

Combine two dictionaries

Semigroup a => Dictionary a -> Dictionary a -> Dictionary a

Note

If a key is in both dictionaries, the values are expected to be semigroup instances, so that they can be combined. Alternative solutions would be to prefer either the first or the second dictionary value as done in Haskell and PureScript, so that there would be no need to constrain the contained type to be an instance of Semigroup. This class provides separate methods Dictionary.append_first() and Dictionary.append_second() for those purposes.

append_first(other)[source]

Combine two dictionaries preferring the elements of the first

append_second(other)[source]

Combine two dictionaries preferring the elements of the second

apply(f)[source]

Apply a dictionary of functions to a dictionary of values

Dictionary k a -> Dictionary k (a -> b) -> Dictionary k b

Note

The resulting dictionary will have only such keys that are in both of the input dictionaries.

apply_first(x)

Combine two actions, keeping only the result of the first

Apply f => f a -> f b -> f a
apply_second(x)

Combine two actions, keeping only the result of the second

Apply f => f a -> f b -> f b
apply_to(x)

f (a -> b) -> f a -> f b

Default implementation is based on apply.

delete(key)[source]
elem(x)

t a -> a -> bool

empty = Dictionary({})[source]
flap(x)

Functor f => f (a -> b) -> a - > f b

fold(monoid)
fold2(monoid)
fold_map(monoid, f)[source]

Monoid m => Dictionary k a -> Monoid -> (a -> m) -> m

foldl(combine, initial)[source]

Dictionary k a -> (b -> a -> b) -> b -> b

foldl_with_index(combine, initial)[source]

Dictionary k a -> (k -> b -> a -> b) -> b -> b

foldr(combine, initial)[source]

Dictionary k a -> (a -> b -> b) -> b -> b

head(default)

Return head (or default if no head): f a -> a -> a

insert(key, value)[source]
keys()[source]
length()

t a -> int

The default implementation isn’t very efficient as it traverses through the iterator.

lookup(key)[source]
map(f)[source]

Apply a function to each value in the dictionary

Dictionary k a -> (a -> b) -> Dictionary k b
null()

t a -> bool

replace(x)

Haskell ($>) operator

sequence(applicative)[source]

Applicative f => Dictionary k (f a) -> f (Dictionary k a)

singleton(key, value)[source]
sum()

t a -> number

to_iter()

t a -> Iter a

Instead of to_list (as in Haskell), let’s provide to_iter. With iterables, we can write efficient implementations for many other methods (e.g., sum, elem) even for large or sometimes infinite foldables.

The default implementation isn’t very efficient as it uses folding to construct the iterator.

traverse(applicative, func)

Map each element to an action and collect the results

For Traversable t:

Applicative f => t a -> (a -> f b) -> f (t b)

The default implementation is based on sequence.

update(f, key)[source]
values()[source]