Tuesday, September 28, 2010

Who Has Moral Obligations?

One of the problems with which I continually wrestle is how to build a durable, non-theistic system of ethics. There are a lot of questions which theistic systems have an easy time answering but which are really quite hard if you don't have god to point to (see here, for example). Most recently my attention has been captured by a corollary to the perennial question "Why behave ethically?". If we accept, for the sake of argument, that there is a good, non-theistic answer to this question, one which quickly follows on its heels is "Who should behave ethically?".

The religious side, as a general rule, doesn't have any problem here. The usual story is that humanity is exceptional, has a soul, is made in the image of god, etc... that's why humans should be moral. The non-theistic view, on the other hand, generally emphasizes that humanity is just one branch on a whopping-great phylogenetic tree. And yet I suspect that there are very few atheists who will claim that other apes, much less whales or cows, have an obligation to behave in an ethical manner. What is so special about humanity that we alone, out of all the myriad species on this planet, should behave ethically?

It's surprisingly difficult to find anything on this subject. There's a lot of material addressing the question "Why should an atheist be moral?", but most of it is descriptive rather than prescriptive in nature, focused on analyzing the motivations for "moral" behavior in atheists. Some germane quotes:

  • The sources of atheist morality:

    Why should an Atheist be moral, without a god to make him to do so? You may as well ask why he should use his head for something besides a mobile hat rack. Morality is a built-in condition of humanity; the moral tendency exists in just about everyone, barring psychopaths.

    ...

    And that, luckily enough, leads us to the foundational principle of morality: empathy. Psychopaths lack empathy with their fellow human beings, and cannot be truly said to have a moral impulse.

  • Is Atheism Consistent With Morality?:
    I, for one, see no reason to believe there are such things. Nor do I think they are an especially useful fiction; the vast majority of people would, I think, behave exactly the same as they do now even if they believed there were no such things as moral facts--they would continue to be guided, as they are now, by their deepest cares and concerns.
  • Pro & Con: Atheists Can Be Moral, Too:
    They are as likely, however, to be guided by sentiment, or instinct, in addition to reason. To answer moral questions, questions about ends and not means, a non-believer will consult "his own heart," Bertrand Russell observed. These questions "belong to a realm...of emotion and feeling and desire...a realm which is not that of reason though it should be in no degree contrary to it." Faithlessness can make moral choices harder; it demands an active inner life as well as a capacity for empathy and engagement with the world.

The above statements are undeniably true, and explain why atheists commonly exhibit behaviors recognized as "good" or "moral", but they don't speak to the concept of ethical obligation. Again, why do we expect ethical behavior from a human but not a cow?

Two of the quotes invoke the concept of "empathy", the ability to identify with the experiences of other entities1, but empathy isn't a uniquely human trait. Many (all?) apes exhibit empathy, as do dogs and mice. As befits an evolved behavior it shows a wide range of expression/variation across these different species. Humans can perhaps be classified, on average, as "extremely empathetic" (if such a designation is meaningful at all), but its clear that we're sitting at one end of a spectrum of behavior shared by a number of other species.

Consider, if you will, the practice of premeditated killing among chimpanzees; can these animals be said to be behaving unethically? Assuming that the consensus answer is "no" we're left with the task of defending that answer in some non-arbitrary fashion. At the same time we have to reconcile the (likely conflicting) verdict we'd render for the psychopath from the first quote, someone congenitally lacking in empathy, for similar behavior. The seeming difficulty of doing so suggests that empathy, by itself at least, isn't enough to explain why we perceive humans, and humans alone, as having ethical obligations.

This is more than just idle philosophizing; understanding who has an obligation to behave ethically, and under what circumstances, is an absolute necessity for any non-theistic system of ethics. Most of the attempts I've seen at answering this question boil down to "follow your conscience", which works fine if you're the only person on the planet but not so well if there are other people about. There needs to be some arbitration mechanism for when individual consciences come into conflict, but non-theistic systems don't ever seem to pan out in that regard.


1 To a first approximation; under the hood "empathy" is a somewhat complicated concept.

Saturday, September 25, 2010

Sigh...

(via The Volokh Conspiracy) Apparently the Federal government is now asserting that it can kill American citizens anywhere, anytime, without judicial review. Two thoughts:

One: This is what happens when you make war on an abstract noun; the "battlefield" is unbounded and anyone can be declared a combatant.

Two: The Obama Administration no longer deserves our respect. They're just as bad as the Bush Administration, if not moreso. It doesn't matter what they've done to improve health insurance if they can't even respect basic civil liberties.

Saturday, September 11, 2010

Some Thoughts On One Justification For The Estate Tax

Weekend Edition had a segment on the estate tax this morning which included an interesting comment by Abigail Disney, grand-daughter of Walt. When asked why she supported the estate tax the had the following to say:

It's absolutely an accident of my birth. And that's sort of the point — that there shouldn't be dynasties built around the simple good luck of being born related to somebody very wealthy.

I found myself wondering what, specifically, she meant by that, since certain interpretations of the above appears to have some fairly radical consequences. Presumably she's not against dynasties per se as the existence of publicly notable families, by itself, doesn't seem morally odious. Rather, her comments seem to be more in line with the views of the luck egalitarians i.e. she has no moral claim to money earned by her ancestors. So stipulated, but there must be more to it than that, since the imposition of an estate tax doesn't follow directly from her lack of moral standing.

Reading between the lines a little she probably feels that wealth-based dynasties needlessly perpetuate social and economic inequalities in our society. Their existence represents a net loss to society as a whole and, consequently, government is justified in impeding their formation through the imposition of swingeing estate taxes. That's an arguable conclusion, to say the least, but its not what got me thinking after listening to the broadcast. Instead I started thinking about the effectiveness of the estate tax as a social leveler and what other interventions might be justified using a similar rationale.

I'm not the least bit convinced that the estate tax represents an effective mechanism reducing societal inequality. The tax doesn't kick in until the gross estate exceeds $3.5 million... that's a whopping great amount of money. Barring an exceedingly large number of inheritors to the estate each one will still be firmly in the "haves" category post-tax. Their wealth may be significantly reduced, but they're still rich relative to the vast bulk of the American populace, so the imposition of the estate tax doesn't materially effect inequality in this regard.

Now, it could be the case that the government effectively re-distributes the proceeds of taxation, thus reducing overall social inequality, but don't hold your breath. Discussions about the budgetary impact of the estate tax (see, for example, here and here) talk about using the revenues thus generated to defray the general expenses of the Federal government rather than directing it specifically to inequality-reducing social programs or anything of that nature. In the end Congress still has to decide to spend the money on worth causes; good luck with that. On cursory review it looks like the estate tax really wouldn't do all that much to address Abigail's concerns; even with the tax in place the rich will stay rich and the poor stay poor.

Now, what about the major premise underlying the estate tax, that the imposition of a grossly disproportionate1 estate tax is justified on the grounds that it provides an (ostensible) net benefit to society? One of the problems with the estate tax as a leveling mechanism is that it simply happens too late; between the time they amass their fortune and the time they shuffle off this mortal coil the worlds' rich grandparents/parents/etc. have ample opportunity to spread their largess to younger relations. From a societal perspective its makes negligible difference if Uncle Sam takes 45% of some rich uncle's estate if he's already paid for the college education of 10 nieces and nephews; those people are permanently better off than the bulk of their peers as a result of that expenditure2.

Following this logic, if we really want to ameliorate the inequalities caused by the accumulation of wealth then you have to stop that wealth from being accumulated in the first place. Question: Would Abigail support a wealth tax? Miss Disney's reasoning is equally applicable in this situation; her very birth into the Disney family is a matter of luck. Moreover, such a tax would, for the reasons outlined above, be more effective at achieving the goal of reducing social inequality. There's still the question of property rights, but once you've gone down the road of supporting an estate tax that doesn't seem to be all that big a deal. A will reflects, after all, a choice made by a living person; that they're dead when its executed makes little difference. If you can take a chunk of their wealth once they're dead there seems no reason why you can't take a similar chunk while they're alive.

I suspect a wealth tax, at least of the magnitude necessary to materially reduce social inequality, would be politically infeasible. But from a purely philosophical standpoint it seems just as justified (if not more so) as the estate tax. If we find the concept of a wealth tax to be unpalatable then that suggests we should re-examine our support for the estate tax as well.


1 Relative to the amount of government resources consumed in the estate transfer process.
2 This is a specific example of a more general observation that, in the US at least, there is a strong correlation (as high as 0.5 if this paper is to be believed) between parental and child income levels. Or, to quote Everlast: "You know where it ends / Yo, it usually depends on where you start".

Saturday, September 04, 2010

More Erlang: Building A File Poller

Suppose you want to monitor a directory and receive notification whenever its contents change? This problem crops up from time to time in various contexts; frequently the directory in question serves as a staging area which holds files prior to processing. When a file is added to this staging area the program doing the processing needs to learn about it in some fashion so that it can be added to the work queue. There are a bunch of ways you might go about implementing such a system, but at heart they generally use one of two mechanisms:

  • Asynchronous event notification: The modification of the directory causes an appropriate message to be propagated to interested parties.
  • Synchronous polling: Some process polls the directory at a pre-determined interval and reports any changes to interested parties.

The former method is more efficient but generally requires assistance from the underlying storage system (i.e. inotify). As far as I've been able to determine1 Erlang lacks support for such a mechanism, so we'll have to use the second approach. Because this is Erlang our goal is to take a basic polling loop and package it up into a separate process that can emit events to some parent.

So let's start with a basic polling loop, omitting function arguments for the moment:

loop() ->
    if 
        sumpin_changed() ->
            send_a_message();
        true -> 
            ok
    end;
    loop().

This would be a horrible CPU hog since it polls continuously, so let's improve the loop by having it sleep between iterations:

loop() ->
    timer:sleep(<some number of milliseconds>),
    if 
        sumpin_changed() ->
            send_a_message();
        true -> 
            ok
    end;
    loop().

We'll also want some way to terminate the polling loop cleanly. In Erlang this is typically accomplished by sending the process a message telling it to exit. In order for the process to catch this message we'll have to introduce a "receive" block in the main loop, which leads to a complication. How do we sleep while simultaneously waiting for an exit message? The Erlang gods have foreseen this particular problem and provided us with a variant of the basic receive block which includes a built-in timeout:

loop() ->
    receive
        exit -> ok;
    after 
        <some number of milliseconds> ->
            if 
                sumpin_changed() ->
                    send_a_message();
                true -> 
                    ok
            end,
            loop()
    end.

That's good enough for now; we'll go back and fill in the details later. Let's move on to detecting new files. This function will need to know what directory to monitor and, for added flexibility, we'll provide it with a regex2 telling it what file name pattern to look for:

get_new_files(Directory, Regex) ->
 Files = get_list_of_files(Directory),
 FilteredFiles = filter_list_of_files(Files, Regex),
 detect_changes(Filtered_Files)
end.

So how do we implement this? list_dir, from the file module, will return a list of all the files in a given directory. re:run can be used as the basis of a predicate for lists:filter to extract only those files which match the provided regular expression.

get_new_files(Directory, Regex) ->
    {ok, Files} = list_dir(Directory),
    FilteredFiles = lists:filter(
        fun(X) -> 
            re:run(X,Regex,[{capture,none}]) == match end,
        Files
    ),
    detect_changes(FilteredFiles),
end.

Now let's stop and think about the best way to detect changes. We could keep a list of files that we've seen before, but such a list may grow infinitely long as time progresses. A less resource-intensive method, which should work well in practice, is to compare the file's mtime attribute (obtained via file:read_file_info) to the time the last polling cycle completed.

This means that we now have a piece of state, the last poll time, to keep track of. Questions to answer:

  • How is this state initialized?
  • How is it updated?
  • How is it passed from iteration to iteration?

To initialize the state we'll want to create an init() function which passes an appropriate initial value to loop(). But what value to pass? In Erlang dates and times are usually passed around as {{YYYY,MM,DD},{HH,MM,SS}} tuples, which makes comparisons a little bit of a pain. To simplify this process we'll convert dates/times to Gregorian seconds3, in which case the last poll time should be initialized to 0.

We want to update the state in such a fashion as to minimize the possibility that some file will slip through the cracks. There's no way to completely avoid a race condition between reading the contents of the directory and getting a new poll time since updates to the directory occur outside of the Erlang process. So what we'll want to do instead is calculate the new poll time immediately after the call to list_dir. Putting this all together with state passing leads to the following:

init(PID, Directory, Regex, PollInterval) -> 
 loop(PID, Directory, Regex, PollInterval, 0).

loop(PID, Directory, Regex, PollInterval, LastPollTime) ->
    receive
        exit -> ok
    after 
        PollInterval ->
            {NewFiles, NewPollTime} = 
                get_new_files(Directory, Regex, LastPollTime),
            if 
                length(NewFiles) > 0 ->
                    PID ! { new_files, NewFiles };
                true -> ok
            end,
            loop(PID, Directory, Regex, PollInterval, NewPollTime)
    end.

get_new_files(Directory, Regex, LastPollTime) ->
    {ok, Files} = list_dir(Directory),
 NewPollTime = calendar:datetime_to_gregorian_seconds(
        { date(), time() }
    ),
    FilteredFiles = lists:map(
        fun(X) -> filename:join([Directory,X]) end,
        lists:filter(
            fun(Y) -> 
                re:run(Y,Regex,[{capture,none}]) == match end,
            Files
        )
    ),
    NewFiles = lists:filter (
        fun(Filename) ->
            {ok, FileInfo} = read_file_info(Filename),
            calendar:datetime_to_gregorian_seconds(
                FileInfo#file_info.mtime 
            ) > LastPollTime
        end,
        FilteredFiles
    ),
    { New_Files, NewPollTime }.

There are a few more changes needed to bring the code up to snuff (see the full source for details), but that's the gist of it. Now let's test it our, shall we?

$ erl
Erlang R13B04 (erts-5.7.5) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0]
[hipe] [kernel-poll:false]
Eshell V5.7.5  (abort with ^G)
1> c(file_poller).
{ok,file_poller}
2> PollerPid = file_poller:init(".",".+\.test",5000).
<0.42.0>
3> lists:keysearch(messages, 1, process_info(self())).4
{value,{messages,[]}}
4> os:cmd("touch 1.test").
[]
5> lists:keysearch(messages, 1, process_info(self())).
{value,{messages,[{new_files,["./1.test"]}]}}
6> os:cmd("touch 2.test 3.test").
[]
7> lists:keysearch(messages, 1, process_info(self())).
{value,{messages,[{new_files,["./1.test"]},
                  {new_files,["./3.test","./2.test"]}]}}
8> PollerPid ! exit.
exit
9> os:cmd("touch 4.test").
[]
10> lists:keysearch(messages, 1, process_info(self())).
{value,{messages,[{new_files,["./1.test"]},
                  {new_files,["./3.test","./2.test"]}]}}

I hook up the Erlang shell to a file_poller process and then create some zero-byte files via touch. Following each invocation of touch the file poller process kindly sends me a message letting me know that there are new files. The process terminated once I sent it the atom exit; no message is generated for the creation of 4.test.


1 One of the challenges of working with Erlang is that, while releases come with decent documentation on a module-by-module basis, such documentation requires you to already have a pretty good idea of what you're looking for. It's less helpful if you need to figure out whether some esoteric bit of functionality is available in the standard library. When I want to know how to do something in Java or Ruby I can just go ask Google, but that approach works less well for Erlang because the community of practitioners is much smaller.
2 The filelib module provides the wildcard function which does something akin to this, but is limited to bare-bones, command-line type regexes.
3 Erlang, being Scandinavian, is an egalitarian language designed to run on a wide variety of platforms. Consequently there's no built-in support (again, AFAIK) for Unix timestamps.
4 process_info is another handy function that could be better publicized. I was looking for a way to peek at a processes' messages when I noticed that pman did just that. process_info is what turned up after digging through the pman source.
Blog Information Profile for gg00