<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Aug 20, 2009, at 5:25 AM, Steven D'Aprano wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>On Thu, 20 Aug 2009 01:36:14 -0700, Paul Rubin wrote:<br><br><blockquote type="cite">Steven D'Aprano <<a href="mailto:steven@REMOVE.THIS.cybersource.com.au">steven@REMOVE.THIS.cybersource.com.au</a>> writes:<br></blockquote><blockquote type="cite"><blockquote type="cite">As near as I can tell, a functor is just an object which is callable<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">like a function without actually being implemented as a function, e.g.:<br></blockquote></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">No it's not anything like that either, at least as I'm used to the term<br></blockquote><blockquote type="cite">in programming or in mathematics.  Maybe it's used other ways though. <br></blockquote><br>According to Wikipedia, functor can be used as a synonym for "function <br>object":<br><br><a href="http://en.wikipedia.org/wiki/Function_object">http://en.wikipedia.org/wiki/Function_object</a><br><br>which is what I was thinking of. So it seems there are at least two <br>meanings for the word, neither of which seems to apply to this thread :)<br><br><br><br><blockquote type="cite">As I'm used to it, it's a feature of certain static type systems.  The<br></blockquote><blockquote type="cite">notion isn't that useful in Python <br></blockquote><br>I find the Haskell page entirely opaque and unintelligible. Well, perhaps <br>not *entirely* opaque, but pretty close: it assumes a mathematical <br>sophistication that I don't think I even had when I was getting my maths <br>degree, let alone can remember two decades later. (Pity the poor VB <br>coders wondering what Haskell is good for...) The Wikipedia page is a <br>little better, but it's section on Examples is laughable -- the examples <br>are as unintelligible to this reader as the description before them.<br><br></div></blockquote><div><br></div><div>To this reader -- an Rb coder -- the examples were pretty clear.</div><br><blockquote type="cite"><div><br>But let me try an example to see if I've got it right:<br><br><br>class Int2StrFunctor:<br>    def map1(self, n):<br>        if type(n) is not int:<br>            raise TypeError('argument must be an int')<br>        return "-"*n<br>    def map2(self, f):<br>        if type(f) is not type(lambda: None):<br>            raise TypeError('argument must be a function')<br>        # assume f takes an int, and returns another int<br>        def inner(n):<br>            return self.map1(f(n))<br>        return inner<br><br><br>The functor can take an int and return a string:<br><br><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">F = Int2StrFunctor()  # F is a functor<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">F.map1(3)<br></blockquote></blockquote></blockquote>'---'<br><br>It can also take a function (of int -> int) and return a new function <br>(int -> str):<br><br><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">def myfunc(n):<br></blockquote></blockquote></blockquote>...     return n+2<br>...<br><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">f = F.map2(myfunc)<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">f(3)<br></blockquote></blockquote></blockquote>'-----'<br><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">f(4)<br></blockquote></blockquote></blockquote>'------'<br><br><br>There's nothing special about the methods map1() and map2(), I could call <br>them anything I like, or even do this:<br><br><br><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">def __call__(self, arg):<br></blockquote></blockquote></blockquote>...     if type(arg) is int:<br>...             return self.map1(arg)<br>...     else:<br>...             return self.map2(arg)<br>...<br><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">Int2StrFunctor.__call__ = __call__<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">F(2)<br></blockquote></blockquote></blockquote>'--'<br><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">F(myfunc)(0)<br></blockquote></blockquote></blockquote>'--'<br><br><br>There are some technical restrictions on functors, relating to the sorts <br>of functions and types (strictly "categories") they can accept, <br>presumably to make them mathematically well-behaved.<br><br><br>Have I got it correct?<br><font class="Apple-style-span" color="#000000"><font class="Apple-style-span" color="#144FAE"><br></font></font></div></blockquote><br></div><div>I don't think so.  Paul Rubin's square example was, I thought, particularly instructive.</div><div><br></div><div>Charles Yeomans</div></body></html>