Wednesday, April 23, 2008

Orators' exercise

I practice this exercise daily. Don't sight read it; read it aloud. The Haskell program that produced this uses a monad; the heart of which is as follows:

-- parses a poem, refering words to CMU for pronounciation

parsePoem = do p ← getContents
return (checkEachLine (lines p))

main = do p ← parsePoem
putStr p


Do you see the monad? Well, that's a rather mean question, because the monad is entirely implied in this program fragment.

One of the motivators for incorporating monads into Haskell was dealing with things in the "real world" that fall outside easy descriptions in purely functional (mathematical) domains. One of those things is input and output. Whereas an equation...

1+1=2


... was true yesterday, is true now, and will be true tomorrow (albeit, it took over 100 pages of introduction to set theory in the Principia Mathematica to be able to back up that truth), things of the "real world", particularly input and output change, and change irrevocably. For example, if I buy and eat some ice cream (mint chocolate chip, please!), I'm not getting a refund. The state of the world has changed: I'm parted from my money, and that scoop of ice cream is no longer in the shop's inventory (and they have a Form 1120S, Schedule A to prove it). Input/output, as part of the state of the world, is one of the members of the awkward squad. So, to help it to be a used and useful language, the Haskell designers included the IO monad as one of the libraries.

So, if one were to query main and parsePoem, one would find that they are the types IO () and IO [Char], respectively, meaning that main interacts with IO, returning "nothing", and parsePoem interacts with IO, returning a list of characters (the poem that you just finished reading aloud).

In short, the IO monad does all the handshaking (or, more correctly, handwaving) with the state of the world, so the programmer can do something as "simple" as printing "Hello, world!" easily. All this monad asks, as every monad asks, is "Pay no attention to that man behind the curtain."

Monday, April 21, 2008

God in the Church

Last week, Fr. Trong gave a homily from the readings, focussing on the baptizing of the 3,000 in one day and the parable of the sheep gate. Now, I look forward to Fr. Trong's homilies, unlike some people, because the level of effort that he puts into each phrase and the depth of knowledge of the Gospel he gives. These homilies are studied, deliberate, affairs, and I appreciate the care for us that he shows in this labor.

Many moons ago I had heard a homily on the sheep-gate. Do you know what a sheep-gate is? It's the gate that keeps sheep in the pen, and wolves at bay. Well, 2,000 years ago, the shepherds didn't use wrought iron fences and gates, they used stone for the fence and their own bodies as the gate. That way, an adventurous sheep (of which there would be fewer over time) would wake the shepherd, but the only thing going over the walls would be predators. Clever, no?


Fr. Trong related these two stories as to our rôles today. The parishioners are the sheep and the priests of the parish, the shepherds. The sheep know the shepherds just as the parishioners and priests of the parish know each other and look out for each other, just as the early disciples in St. Peter's time. Anything or anyone else is a wolf, even if it's wearing sheep's clothing. So, Fr. Trong concluded, the laity should stay in their parish.

I can see Fr. Trong's point, and agree with 99% of it. Most parishioners should stay in their parishes and learn from their parish priests, because this arrangement is edifying for most parishioners.

But let's look at the history of the Church. Does growth toward God come from within the bureaucracy and the magisterium? Or, does it come from without? This is an important question, especially in light of the most visible symbol of authority, Pope Benedict, to this country. Well, let's examine how the Church has grown throughout history.


  1. Abram, an idol-maker's son, intuited the the presence of God from outside the prevalent pan-theistic cults.

  2. Jesus, the most perfect Jew ("Not a jot or tiddle" [Matt 5:18]), supplanted the prevailing Rabbinic monotheistic rule of the Pharisees and Sadducees with the worship of a Triune God

  3. St. Peter and St. Paul (né Saul), interpreting Jesus' words and acts, expanded God's people from the Jews to include the Gentiles

  4. St. Augustine, Doctor of the Church, notorious for his licentious youth, did some studying outside of the Torah: he was heavily influenced by Platonic works, and used that influence to make Christianity accessible to the Western/Latin world.

  5. St. Thomas Aquinas, Doctor of the Church, the Arc of Salvation, used the philosophical methods of the heathen, Aristotle, to explain and to prove rigorously the tenets of Faith

  6. St. Jeanne d'Arc was burned at the stake by the Church authority for following the voice of God

  7. St. Thérèse de Lisieux had to petition the Pope, against the vehement objections of her parish priest and bishop to enter religious life.



So, with the exception of 3. above, if we were always to listen to the local church authority, we would still be:


  1. idol-worshipping pantheists

  2. Jews awaiting the Messiah

  3. n/a; church authority got this one, as it got many others, right

  4. idol-worshipping pantheistic slaves of Roman rule

  5. dumb servants of faith, disallowed to use our God-given gift of reason

  6. less French??? Okay, I don't have a good counter-example here, but I'm sure something along the lines of nationalism, patriotism and self-governance can be thought up here by someone quicker than myself

  7. unable to see God in the "Little way"



Again, let me stress, that following the teachings of the Church and Church authority in their parishes is what makes Catholics, Catholic and is one of the pillars of the Church. But, the Church body is composed of fallible human people organized by bureaucracy, and, as such, may occasionally fall into error, may entrench into established ways for dogmatic, not salvific, reasons, and may react to perceived outside threats with a hand that is sometimes too heavy (just ask Galileo about that). When God knocked Saul off his horse, no concerns of the local church were going to stop his new evangelization. God calls each of us, but that calling, for most of us, is to follow our vocation in our homes and in the pews to be edified by the local parish priest, but when God calls in a particular way, it is for the overall good of the Church, and not objections, nor even martyrdom by the people in that Church can stop God from carrying out His Will to bring the People of God to Himself.

Sunday, April 6, 2008

Trivial Monad solutions (cont.)

This is a continuation of the previous entry on the subject, with the solutions for exercises 3 and 4. But, we are now finally and formally introduced to the Haskell-style bind operator: >>=. What >>= (which is pronounced: "bind") does is to give the value the monad contains to the function that then uses it. More formally defined (specific to sigfpe's trivial monad example):

W a >>= f == f a

An example of the syntax (again, following sigfpe's post) is as follows:

W 5 >>= f


(where f was defined in sigfpe's post as an increment function for his trivial monad: f x = W (x + 1)). The above example would result in the (monadic) value W 6. So, now you see >>= (trivially) in action, and sigfpe asks us to put it into use for the following exercises.

The first exercise that we'll continue on in this entry is exercise 3, which is to prove the three monad laws:

Left Identity: return a >>= f == f a


or, a monadized value bound to a function is the same as applying a function to the plain value.

Right Identity: m >>= return == m


or, a monad bound to return is just that monad, again (or, the identity function for monads is bind return), and finally:

Associativity: (m >>= f) >>= g == m >>= ((λ x . f x) >>= g)


which is similar in spirit to associativity for addition, i.e.: (a + b) + c == a + (b + c).

Just a side note here, some people become discouraged when they are told "to prove" something, whereas if they are asked "to solve" a problem, they turn right to it. Fogel and Michalewicz rightly point out that proving and solving are basically the same process!

My cara spoza asked me, as I was attempting to (re-)prove liftM2 (+) for exercise 2, "Is proving difficult?" The question gave me pause: "Well, sometimes the simplest proof can elude me for days, and sometimes something that appears much more difficult comes in a flash."


So, let's prove each of these laws in turn, using the definitions of >>= and return as axioms.

First up, Left Identity:











Prove:return a >>= f ==f a 
1.return a >>= f == W a >>= f return definition
2.  == f a >>= definition
Q.E.D. 

Next, Right Identity:



















Prove:m >>= return ==m 
1.m >>= return == W a >>= return monad identity
2.  == return a >>= definition
3.  == W a return definition
4.  == m monad identity
Q.E.D. 


And, finally, let's prove associativity. We'll start out by reducing the left hand side ("lhs") to something simpler:










Simplify:(m >>= f) >>= g  
1.(m >>= f) >>= g == (W a >>= f) >>= g monad identity
2.  == f a >>= g >>= definition


... but it was here that I became stymied, for I didn't see how to transform f a >>= g into something resembling the right hand side (rhs), which is m >>= (λ x . f x >>= g). Do you? Give it a try!

...

The thing to do, when one becomes stuck solving or proving something, is to acknowledge that fact, and then to try something entirely different. One way to try something different is to rework the simplification of the lhs so it assumes a form much closer to what the rhs is. I didn't see this approach to be fruitful, however: I reduced the lhs to be something pretty simple, so a rework would make the lhs more complicated -- clutter often obscures correlation. Another approach is to leave the lhs be and work on simplifying the rhs -- maybe a simplification there would yield an useful correspondence. Let's do that:














Simplify:m >>= (λ x . f x >>= g)  
1.m >>= (λ x . f x >>= g) == (W a >>= (λ x . f x >>= g) monad identity
2.  == (λ x . f x >>= g) a >>= definition
3.  == f a >>= g β-reduction


Ha! Now we see that the simplification of the lhs is identical to the simplification of the rhs. That was easier than expected.

Q.E.D.

To summarize this exercise, proving something or solving something is really a rather simple task: using the tools you have to match the solution to the problem. The fun part comes in when you discover new ways to use the given tools, or, finding out the given tools aren't sufficient, which means finding new tools to solve the problem. Once you have your tools, along with the problem statement and desired outcome, it is often the case that there is a simple walk from the problem to the solution, the solution to the problem, or both meet somewhere in the middle. Odds are, you are not the first one solving a problem, if you need help, there's a whole big world out there -- someone probably has already left the solution out there for you to find.

Exercise 4: Monads cannot be unwrapped completed back to the plain value they carry, but if a monad is layered, that is a monad contains a monad, it is possible to remove one or more layers. join is such a function that does this "unlayering". Given a layered monad mm = W (W x), join mm will return the value W x. The declaration for join is:

join :: W (W a) ⇒ W a


Define it.

Solution 4: Well, the declaration for join looks suspiciously like an application of >>= (you are pronouncing that operator "bind", right?), as it hands the value carried by the monad for function application.

join mm = mm >>= ?f?


The question then becomes "what function to apply the carried value to?" The problem is that >>= has already given us the answer, W x, so we just wish to have join return that value unaltered. Fortunately for us, there is such a function from combinatory logic called the identity combinator, I, which has the form λ x . x, and Haskell already has that definition (it is named id), so we simply use that for the hole in the above definition:

join mm = mm >>= id


Q.E.D.

In conclusion, I hope these entries have helped you to see that monads are actually a rather simply concept that are easy to use. This is just the tip of the iceberg, however: monads are used pervasively in Haskell, tackling a great many tasks. May I suggest the excellent and practical tutorial on Monad Transformers? Please do not be put off by the imposing front page to the paper, as this tutorial shows how monads and their transformers shine, giving a step-by-step introduction of new functionality of monads into a plain-vanilla system.

Saturday, April 5, 2008

Trivial Monad solutions

Okay, a monad is a mathematical form, which sigfpe describes in his blog. He then proposes a series of exercises [reminiscent of my own exercises in combinatory logic], and even provides solutions. I came up with quite a different solution set, as I used his entry, and his entry only, as the source material.

A recap of monad: a monad is an opaque decorator. It takes a thing (including taking nothing) and hides that thing behind the monadic form. In sigfpe's example, the monad, W, takes a number (or anything else, for that matter), consuming it.

A monad, then, is like a katamari or a black hole, ... or Kuzko: no touchy!

So, then, the question naturally arises: how does one interact with the captured data? Well, the monad interface provides two basic operations in its protocol: return and bind (sometimes written >>=).

  • return "lifts" an object into the monadic form. In propositional logic, return is a ⇒ M a -- 'return 5' would yield 'W 5' in sigfpe's example.

  • bind takes a function that transforms an object to a monad and converts that function that transforms the object within that monad. In propositional logic, bind is (a ⇒ M b) ⇒ (M a ⇒ M b)


So, bind is used frequently when working with data and their monadic forms, and from it other functions may be derived, such as fmap, which maps (converts) a function that works on "ordinary" data to one that works on monads ... fmap is (a ⇒ b) ⇒ (M a ⇒ M b). Note the closeness to bind: the derivation of fmap is λ x . bind (return • x) (where • is composition (the B combinator, or Bluebird, from combinatory logic), and λ introduces a variable in the expression).

The above is enough introductory material to solve sigfpe's first two exercises, which I reproduce here:

Exercise 1: Write a function, g, that adds a number to a monad containing a number, returning a new monad with the sum, or g :: a ⇒ M a ⇒ M a.

Solution 1: well, given that addition is of the form (+) :: a ⇒ a ⇒ a, and that fmap lifts an ordinary function to a monadic one, the solution nearly writes itself:

g x my = fmap (+ x) my


What is simply done here is to construct a "plus x" function by applying x to the addition operator -- note that (+x) :: a ⇒ a. We then lift that function to its monadic equivalent with fmap and apply the result to the number (y) contained in the monad (my). Q.E.D.

Exercise 2: Write a function, h, that adds monadic numbers, returning a new monad containing the sum, or h :: M a ⇒ M a ⇒ M a

Solution 2: This provided a spot of bother for me. Whereas in the last solution, one could take the first number and apply it to addition to come up with a function that fit the form of fmap, in this case, we don't have any numbers with which to simplify addition to a form we can use, as they are all rolled up into monadic forms.

I described the problem thusly to my daughter, EM.

Me: You know addition, right?
EM: What's that, Papa?
Me: What's one plus two?
EM, immediately:Three! ... and ten plus ten is twenty! ... and twenty plus twenty is thirty! ... and thirty plus thirty is forty!
Me, clearing my throat, letting the errors pass in light of the delighted exuberance with which she delivered her answers: Um, yes, well. Here's my problem, let's say Thing One has a number hiding behind its back, that it won't show you, and Thing Two has a number hiding behind its back, too, that it won't show you, and you're asked to add those two numbers and give the answer to Thing Three. How do I do that?
EM, rolling her eyes: Papa, there isn't a Thing Three in the Cat in the Hat!
Me: Yes, well, suppose there was; how would I do this?
EM: Can you peek behind their backs to see what the numbers are?
Me: No, you're not allowed; besides, those Things are much too fast to run behind them, remember how they ran through the house with kites? ... So, we must use something like the fmap-box-maker, because addition is a box that takes numbers and yields numbers, but we need a box that takes Things and yields Things.


Using fmap does work its way into the solution I eventually derived, but another important player for this solution is also bind used in conjunction with a technique of deferred computation.

You see, just like the solution for exercise 1, we'd like to apply a number to addition to obtain a function for use by fmap. The problem is that we have no such number (just monadic values), but this is where bind is of use. Recall that bind :: (a ⇒ M b) ⇒ (M a ⇒ M b). The standard given explanation of bind is that it transforms a function that lifts ordinary data into monads to a function that works entirely in the monadic domain. But an entirely different way of looking at bind is that it treats a given monad like ordinary data as input to the lifting function. εὕρηκα! [No, I'm not about to hop out of the tub and run around town with my towel flapping in the wind]

The latter usage is the only one for those using >>= (which has the English language pronunciation of "bind", as well, confusingly), but if we take sigfpe's entry as the sole and base source, this "discovery" is quite the epiphany. And with that understanding, along with some deferred computational hand-waving, the solution then, again, presents itself:

h w1 w2 = bind (λ x . fmap (+ x) w2) w1


Working from the parenthetical expression outward, we again see the fmap (+ x) form, unaltered from the solution to exercise 1, giving us a number-to-monad function. The catch here is that we have no such number, so we give a promise that there will be such a number eventually with the λ-introduction. We then immediately fulfill that promise with bind: we apply the number-to-monad function to w1, treating that monadic value as if it were a plain number (that's what bind gives us permission to do), rendering the solution. Q.E.D.

Critique

I obtained solution 1 almost immediately by matching the logic of fmap to that of the problem description. It seemed to me to be rather trivial, so I was taken aback at the lengths and "arcane-ness" that sigfpe put into his solution.

On the other hand, sigfpe merely needed to augment his first solution with variable introduction to obtain his second solution. His second solution was trivially-obtained and obvious, given his approach to the first solution, whereas I had to struggle quite some time -- introducing both λ-abstraction (as sigfpe does) and bind (which sigfpe already had in the alternate syntactic form of >>=) -- to obtain mine.

In my defense, my solutions use only the monadic tools introduced in sigfpe's blog entry. On the other hand, Haskell programmers accustomed with monads rarely use fmap, regarding it as esoteric or superfluous, and instead rely on >>=, or inline binding entirely with the more "natural" do-notation (although there has been some grumblings against it), so in the light of that experience, sigfpe's solutions are natural and the first way most Haskell programmers would solve these exercises. This entry here, then, is from the perspective of someone not familiar with Haskell's approach to monads deriving the solutions from the principles of the provided function bind and its derived sibling fmap as discussed in sigfpe's blog entry.

Please see my next post for the solutions to sigfpe's exercises 3 and 4.

Wednesday, April 2, 2008

God Be With Ye, Joel

My friend, Joel, just died this week, suddenly, leaving my friend, Sandy, a widow. The Apostle Paul writes: "God is no respecter of persons." [Rom. 2:11], but I certainly am, and there are very few people in this world that have earned my respect -- Joel was one of them. He and I could not have been any more different: his introspection foiled my exuberance, his patience, my wrath, his acceptance, my judgements. I think it boiled down to, essentially, his Irishness to my Italianness. Yet, as Sandy knows best, these two seemingly opposite characters did not clash, but deepened our friendship, and my respect for him over the 18 years that I've known him.

We all know the story that the Irish never say a bad word about the dead: a lady asked to speak on behalf of a man, universally reviled, who just died, struggled for a moment, then burst into a smile as she pronounced: "But he had a brother who could sing." For Joel, I have the opposite problem: I cannot recall one moment where he ever lost his cool or exposed himself to censure. For Joel, everything was alright or would work itself out, and he was there, doing his part to make that so. He was always warm in his greeting, in his inquiry, and took your causes, making them his own.

For example, it was Joel who got me on my feet after I left the military with my first job working at his company. He tried me in one role, working for him in marketing, but seeing I was more fit for computers and software, quickly shifted gears and championed me to the IT managers. He did this over and over again for so many people he came across -- he truly liked to help people, he didn't particularly care that this or that person did or didn't fit Joel's assigned position, he just helped to find the best fit for the person he was helping, regardless of his own benefit. I have rarely seen this egolessness in service: when I saw Joel doing this I saw it come from a rock-solid foundation of faith. He knew he was doing his part to help things along, so he had not one concern about the benefits to himself.

He was introspective and studious by nature -- his most natural pose was one of repose, with a book in his hand. But, at the same time, he enjoyed company. At a business function several years ago, Joel opened his house to me and three other young men for a lunch, prepared by Sandy, that I will never forget. The food, of course, was a very welcome respite from the starched business setting, but what I took away with me was Joel's absolute peace and comfort. It seemed to say: "This is my house, this is my home: I'm comfortable in it, and I'm comfortable sharing it with you." Our dessert was an Irish coffee Joey lovingly hand-measured that I have not tasted the like before or since. Joel was a stately craftsman: proud of his work, and pleased to share it.

I shall end with this: his service and conduct were a credit to himself and his family, and we sorely miss him. God bless you, Joel, may you rest in the company of the saints.

Monday, March 31, 2008

Sunday, March 30, 2008

My Cara Spoza, Sweet and Dainty

I attended a family gathering of mi cara spoza's; it was a small party this time, there were only 40 or so people with family, friends, friends of friends and moiself (that is French; and yes, you must figure out why I listed moiself (that is French) separately). As Li'l Iz was sick (flu, 103.4o temperature), I was not greeted, instead they looked at me, and asked politely, "Where's Diane?" (they were not impolite, so they didn't ask: "Who are you?") After I explained that she was looking after the sick girl, they coo awhile over EM ("She's soooooooooooooo sweet! She brought presents for her cousins!" because EM likes giving letters, drawings, and presents to her friends) and direct me to the food: "Eat! Eat! Eat!" No, they're not Italian, they're Philippinas.

Well, since Diane wasn't there, the subject of conversation naturally turned to her.

Them: Oh, you must miss her!
Me: Yes, terribly
Them: Ahhhhh! ... what do you like most about her?
Me: Oh, that she's sweet and dainty!
Them, puzzled: Yes, quite.


They must not get my sense of humor, because Diane is very sweet, pixie-like, one might say, but dainty? ... no. So, after a polite pause (yes, Diane's cousins are very polite, I already said they're Philippinas, right?), the conversation resumed.

Them: Well, she may be dainty, but she has her own mind ... you wouldn't want to mess with her.
I agreed: Oh, you could mess with her, but only if you wanted to lose.


This assent brought on much laughter and kibitzing (they call it tsizmis), and soon after eating some delicious cake, I excused myself to trade places with Diane to watch over the sickly child.

Me: Elenas, I'll be going home now, and Mama will be coming here; you may stay and play with your cousin Trisha.
EM, playing with her cousin, Trisha, not giving me a backward glance: Okay


I then thanked all 40 hosts and hostesses, and on my way out, I was confronted by little Trish: Why aren't you gone yet?

Well, I guess I don't need to worry about separation anxiety ...