I found an article like the one above, so I thought I'd like to do it in Python too ^ ~ ~, so I tried it a little.
First of all, from the implementation of the function for function synthesis (g ∘ f) (x) = g (f (x))
def compose(f_t_u, f_u_r):
'''
:type f_t_u: t -> u
:type f_u_r: u -> r
:rtype: t -> r
>>> comp(lambda a: a + 'oppai', lambda b: b + 'hoge')('')
'oppaihoge'
>>> comp(comp(lambda a: a+'oppai', lambda b: b+ 'hoge'), lambda x: '[' + x + ']')('')
'[oppaihoge]'
'''
return lambda t: f_u_r(f_t_u(t))
I tried to put something like a type annotation, but I'm not sure if it's easier to read.
By the way, the function composition is done above, but the parentheses are full. Scala I'm not sure, but the original article seems to use operators and implicit type conversions to get rid of parentheses. Scala scared
However, Python cannot define the oleore operator in the first place.
So, here we will work on the neutralization of the function. Everyone loves __ror__
, __or__
overloads and rewrites the compose.
class infix(object):
def __init__(self, function):
self.function = function
def __ror__(self, other):
self.left = other
return self
def __or__(self, other):
return self.function(self.left, other)
def __call__(self, value1, value2):
return self.function(value1, value2)
@infix
def c(f_t_u, f_u_r): return lambda t: f_u_r(f_t_u(t))
Well, with this
(str.upper |c| sorted |c| set)('abcdeabc')
# > set(['A', 'C', 'B', 'E', 'D'])
You can now write like this.
Finally, let's implement a container called Ap that appears in Part 2 of the original article. Use the right bit shift operator to take the function and use it as appropriate.
class Ap(object):
def __init__(self, val):
self.val=val
def __rshift__(self, func):
return func(self.val)
By using this guy
Ap('abcdeabc') >> (str.upper |c| sorted |c| set)
# > set(['A', 'C', 'B', 'E', 'D'])
I can now write. I've done it.
There are still parentheses left, but it's okay to finish. I like this because it's interesting, but I don't think it's practical because I don't think it's Python-like.
# Addendum
Implementation of Ap class
class _Ap(object):
def __rlshift__(self, other):
self.value = other
return self
def __rshift__(self, other):
return other(self.value)
Ap = _Ap()
a = Ap
If you do
'abcdacb' <<a>> (str.upper |c| sorted)
#> ['A', 'A', 'B', 'B', 'C', 'C', 'D']
It's like this. This is a visual closer to the original article, and it gives a more apply feeling (?)
Postscript:
It's less versatile, but I've also written something that looks like Haskell and has an atmosphere that allows function composition with .
.
[Haskell synthesis operator. In Python ~ Implementation of Collection processing by function synthesis](https://hachibeechan.hateblo.jp/entry/implements-the-haskells-compose-function-in-python-and-list- processing)
Recommended Posts