Last active
December 20, 2021 21:41
-
-
Save 3noch/eef18dba108be7db0441 to your computer and use it in GitHub Desktop.
Functors in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import types | |
| global fmap_vtable | |
| fmap_vtable = {} | |
| def fmap_for(type): | |
| def register_fmap(func): | |
| fmap_vtable[type] = func | |
| return func | |
| return register_fmap | |
| def fmap(fn, data): | |
| return fmap_vtable[type(data)](fn, data) | |
| apply = lambda fn, data: fn(data) | |
| fmap_for(types.NoneType)(lambda fn, data: None) | |
| fmap_for(int)(apply) | |
| fmap_for(str)(apply) | |
| fmap_for(float)(apply) | |
| fmap_for(bool)(apply) | |
| fmap_for(list)(map) | |
| fmap_for(dict)(lambda fn, data: { key: fn(value) for key, value in data.iteritems() }) |
Author
This is so programmer-friendly an approach that I am inclined to pour it into a small and terribly useful and extremely light weight library I would call fmap. Would that be allright with you? (I don't know how this is licensed)
I want it to follow the motto 'make simple things simple, and hard things possible` (https://www.quora.com/What-is-the-story-behind-Alan-Kay-s-adage-Simple-things-should-be-simple-complex-things-should-be-possible/answer/Alan-Kay-11?ch=10&share=7a78ffce&srid=88EK)
pip install fmap>>> from fmap import fmap, register_functor
>>> numbers = dict(one=1, two=2, three=3)
>>> fmap(lambda x: x*x, numbers)
{'one': 1, 'two': 4, 'three': 9}
>>> # and work with typings, too
>>> from typing import Optional
>>> register_functor(Optional, lambda fn, data: fn(data) if data else None)
>>> fmap[Optional](lambda x: x*x, None)
None
>>> fmap[Optional](lambda x: x*x, 3)
9
>>> fmap[Optional](lambda x: x*x, dict(one=1, znox=None, three=2)
{'one': 1, 'znox'=None, 'three'=9)}
...
Author
Cool! Thank you.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a Python implementation of Functors from category theory (and a relatively common concept in FP languages). The term "Functor" can be easily confused with its colloquial usage in C++, and some other languages, where it has essentially come to mean "Callable."
However, in category theory, Functor refers to "a mapping between categories." To a programmer, this basically means that a Functor is simply a mapping from one type of data to another, with a one important restriction. In general, a "mapping from one type of data another" can basically be any sort of conversion. For example,
json.dumpsconverts a dictionary to a JSON-formatting string. Butjson.dumpsis not a Functor, because there is one important law that a Functor must obey: the shape of the data cannot change. The easiest example of a true Functor is themapfunction. It takes a list and returns a list whose elements are modified. If youmapthestrfunction onto a list of numbers, you are mapping from one data type to another, but the shape has not changed. The input and output are both lists.