Planet HCoop

September 08, 2017

Sajith Sasidharan (sajith)

Area Man (Kinda) Figures out How to Use CPack

Lately I have been working on a C++11 project that uses CMake. I find CMake to be approachable, useful, and sometimes somewhat weird. But it gets the job done.

I suppose I should document what I have managed to learn so far (which is: just enough to be useful), and I will do that in due time, in a regularly scheduled future weblog update (haha).

For now here are some notes about a thing I struggled with, for longer than I should have: making an RPM package from ye olde CMake project.

CMake ships with a companion program, CPack, which makes creating binary packages easy. All you need is a line like this in your top-level CMakeLists.txt:

include(CPack)

Our project generates the good ole Unix Makefiles, so I should have been able to do just run some commands and get on with my day:

$ cd $BUILDDIR
$ cmake $SOURCEDIR
$ make package # or just run 'cpack'

As we know nothing in computering land works that way.

With the basic configuration, the above produced three packages: a self-extracting shell script, a tar.gz package, and a Unix compressed .Z package. But here's a problem:

$ ls -l project-0.1.1-Linux.*
-rwxrwxrwx 1 sajith sajith 3818 Sep  8 10:35 project-0.1.1-Linux.sh
-rw-rw-r-- 1 sajith sajith   29 Sep  8 10:35 project-0.1.1-Linux.tar.gz
-rw-rw-r-- 1 sajith sajith   54 Sep  8 10:35 project-0.1.1-Linux.tar.Z

They are all empty! Also I still do not have that RPM package I needed. So I set the CPACK_GENERATOR variable before the include(CPack) line:

set(CPACK_GENERATOR "RPM")
include(CPack)

In order to have the intended artifacts (binaries, documentation, etc) inside the archives, I also needed some install lines in the appropriate CMakeLists.txt files. (We have not been "make install"-ing our project, so we had omitted the install lines. CMake-built binary packages get their contents from the install step, and it took a bit of figuring out.)

install(TARGETS binary DESTINATION bin)
install(DIRECTORY project-config-files DESTINATION etc)
install(FILES README.txt DESTINATION share/doc/project)

With that, I have a basic RPM file. For further customization, there are a bunch of extra variables that we can set:

set(CPACK_GENERATOR        "RPM")
set(CPACK_PACKAGE_VERSION  ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_RELEASE  1)

set(CPACK_PACKAGE_NAME                 "usual-widgets")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY  "Some usual widgets for day-to-day use")
set(CPACK_PACKAGE_VENDOR               "Usual Business Corp")
set(CPACK_PACKAGE_CONTACT              "Your Humble Packager <packager@example.net>")

set(CPACK_PACKAGING_INSTALL_PREFIX  ${CMAKE_INSTALL_PREFIX})
set(CPACK_PACKAGE_FILE_NAME         "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}")

set(CPACK_RPM_PACKAGE_LICENSE  "GPLv3")
set(CPACK_RPM_PACKAGE_GROUP    "Applications/Internet")
set(CPACK_RPM_PACKAGE_URL      "https://project.example.net/packages")

We can also instruct CPack to generate additional kinds of packages:

set(CPACK_GENERATOR  "RPM;DEB;TGZ")

And there are more knobs to turn:

set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
set(CPACK_DEBIAN_PACKAGE_VERSION      1)
set(CPACK_DEBIAN_PACKAGE_SECTION      "Network")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE     "https://project.example.net/packages")

Another thing I figured out is that I can set CMAKE_INSTALL_PREFIX to somewhere other than the default /usr/, when running cmake:

$ cmake -DCMAKE_INSTALL_PREFIX=/opt/UsualBusinessCorp/ $SOURCEDIR

I still do not know how to sign the packages, etc., but then again, this is just enough to be useful, and that is all I need.

Extra: verbose output

What if I need a little more verbose output from CPack?

cpack -V -G RPM -D CPACK_RPM_PACKAGE_DEBUG=1
cpack -V -G DEB -D CPACK_DEBIAN_PACKAGE_DEBUG=1

Extra: the dreaded comma

Here's a frustrating but really silly thing I dealt with: I inserted an extra comma in one of the set() directives by mistake, and then spent an inordinate amount of time figuring out why things weren't working the way I thought they should be working.

CMake silently ignores the directive when you do set(VAR, VAL): it has to be set(VAR VAL) or CMake will do its thing and not the thing you're asking it to do. You do not want this to happen.

September 08, 2017 05:00 AM

August 23, 2017

Steve Killen (nevetski)

Moments of transition

Well, we have unpacked, gone to Ikea for shelves, and set everything up. We are officially residents of Ellicott City, MD :) My better half has begun working, and she is thriving wearing the many hats that the job requires.

Time is going to take on a different sense now that I am a SAHD; indeed, it already has. I have been trying to write this post for about three weeks. No car means being creative about seeing friends, and generally more isolation. But there is lots to do here in EC! The Boy and I hike down to the Trolley Trail on a mostly daily basis, and we play with his train set, and I subsume myself in keeping the house running: cleaning, cooking, getting groceries, etc. It is a way to channel my anger at the current state of national affairs.

But it’s not just national news that is getting me angry–it filters all the way down to my family and friends, so divorced from the web of the people around them that they let their bigotry hang out like yesterday’s laundry on the line. I stand my ground, and choose my battles–but the void of reason remains. The insulation of their line of thinking makes them impervious to the very real damage they’re doing to American discourse, and their support of this kind of thinking at the highest levels of national office means that the damage is nation-wide. They go on about fake news, and then turn around and spread fake news, which they defend from a position of simple intransigence. It’s infuriating.

I am grateful for the opportunity to see the Boy grow in real time, and to see and talk to friends as they allot time for us. And gratitude is what carries me through these times most of all.

by Steve Killen at August 23, 2017 01:22 PM

July 29, 2017

Clinton Ebadi (clinton)

July 21, 2017

Steve Killen (nevetski)

This brave new world

Two years, and how life has changed. (And somehow remained the same…)

After an adventure abroad in South Korea and Vietnam, we have moved back to Maryland, and it feels like home. My wife has made the leap into her career as a plant nursery manager for a watershed restoration non-profit, coming from the Piedmont to save the Chesapeake Bay. Somehow, North Carolina was always terra incognita. So, rather than spend a few weeks each year returning to the Old Line State and spending the rest of the year pining for my beloved friends and family, I return with my family. My son (a Tar Heel born) has spent over half his life outside the US, which will only change on his second birthday. I used to say–never having  left the US–that I was a citizen of the world. I feel that title truly belongs to him. We are the wings that lift him up, beating on to sustain his flight to heights undreamed.

I followed the election closely last year, and it is difficult to contain the feelings that arose afterwards, continuing onward through the transition and into the new presidency and Congress. A thousand Cassandras spelled out the doom that would follow, and yet I still see people surprised by events that unmask the professional grifters we have elevated to high office. I dedicated my life to truth a very long time ago, and to see such blatant disregard for it promulgated by friends and family rocks me to the core. It is a wound of the psyche, difficult to bear even as we live our lives in quotidian dismay and joy. My son and wife are my reminder that we still have power to change the world, by learning from our mistakes and teaching our children a better way.

Ever the Knight of Cups, I return to writing as the challenges of life ebb and flow. I succeeded in completing NaNoWriMo again last year, and the world of Maroon is more vivid in my mind than ever. The Boy guarantees that it comes in fits and starts, but my resolve has only wavered, never vanished. I tried writing groups, but the effort of keeping up with the group crowds out time for writing itself. It is a truism that people understand only after parenthood the meaning of not having enough time. We fritter so much away and call ourselves bored when we merely fail to perceive the gifts before us untouched. I have let drop so many connections with friends and family in the face of overwhelming responsibility, but as we emerge from the woods of our son’s infancy into the meadow of his burgeoning independence, I resolve not only to write but to connect.

Habitica or Google tasks seem reliable choices. (To this day, I mourn the passing of the Handspring Visor, and with it the Calendar+ app, set to Sinead O’Connors “Nothing Compares 2 U.”) I must try to avoid the trap of futzing with the medium too much, though. My life as someone with ADHD is a song of distraction and immediacy. Too often I absorb my stress into video games. But if, instead of playing games that merely pass the time, I make my life into a game of sorts (a la Habitica), that may serve.

Thanks for listening, even amidst the silence.

by Steve Killen at July 21, 2017 02:28 AM

March 30, 2017

Clinton Ebadi (clinton)

An(other) Open Letter to Representative David Price

I previously wrote David Price after learning of HR 676‘s reintroduction this year, and received no response (not even a paltry form letter sent by an intern). Since the issue is back on the table, I decided to give it another shot. Feel free to borrow some of my ideas.

Representative Price,

I am writing you a second time about HR 676, the Expanded and Improved Medicare For All Act [0] which your colleague John Conyers is yet again introducing, and to request that you cosponsor the legislation.

As you are likely aware, Senator Sanders has announced plans to introduce either a Medicare for All or Public Option in the Senate in the coming weeks. With the collapse (and moreso with the grumblings of revival) of the AHCA efforts, it is my opinion that the time is ripe for Democrats to show that they are still capable of pushing for social progress, instead of merely defending the status quo as seems to be their way in recent years.

My hope is that strong support for HR676 in the House will result in a Senate version, instead of a watered-down Public Option that is, purely from a financial perspective, doomed to failure as it would be forced to take on the sickest citizens and would not have the needed clout to effectively manage costs.

Although I was unable to take off of work to attend any of your recent Town Halls, I was glad to read [1] that several of my fellow constituents asked about your stance on single-payer and called upon you to support Medicare for All. I was, however, disappointed hearing that your response was not one of support, but a declaration it was off limits for another 20 years.

A progressive party cannot progress society if they lack forward thinking ideals and goals. I fear that the democratic party has now become a conservative party, fiercely defending the status quo, attacking progressive politics, and having the mere appearance of progressiveness relative only to the republican party now that it has devolved into a regressive party of neofascists.

Although it is true we still need to defend and expand basic access to healthcare, and perhaps the bill would be dead on arrival this session, I still believe your party supporting it would go a long way toward repairing your tarnished image with the public, possibly ensuring strong wins in the House and the ability to push positive legislation come 2019.

There is also the human cost — at a time when the majority of your constituents support a single-payer system, when insurance company profits are bolstered by the private-industry bailout of the ACA, when real health care costs are unaffordable for far too many despite nominally having insurance — you ask us to suffer and die destitute upon the streets for twenty more years before even considering the idea that profit and human health are incompatible?

Economic reality supports single-payer sooner than later as well — all resources expended enhancing the intrinsically broken for-profit healthcare industry instead of building up a public not-for-profit one is wasted, and with each year the population grows and ages, and the problem of building a public system sufficient for all becomes that much more financially disruptive; perhaps insurmountable.

We simply do not have time as a society to delay more than another four years (and even that is too long, but your party decided against single-payer when there was a chance, and I suspect the current President wouldn’t be amenable to signing such a bill). If the discussion is not started now, the prospects for passage in time to save the country from a public health crisis not seen since the 19th century seem dim.

I end my plea with a warning — I suspect you are aware of the strong support for Sanders during the 2016 primary in your district, and the growing disaffection with status-quo democrats. A failure to take a stand for something so popular reinforces the perception that your party no longer cares to represent the common citizen.

I am already leaning toward lending material support to any more progressive primary challenger for your seat, and your refusal to make a stand with HR676 will certainly seal that decision. The North Carolina Green Party also may very well have ballot access in 2018 (emboldened by a recent 11th circuit ruling [2] they have now filed to overturn our ballot access laws as unconstitutional [3]), so you may no longer rest easy, assured that your gerrymandered constituency will re-elect you without challenge.

Best Regards,

Clinton Ebadi

[0] https://www.congress.gov/bill/115th-congress/house-bill/676]
[1] http://carycitizen.com/2017/03/07/david-price-talks-health-care-budget-cuts-in-cary-town-hall/
[2] http://www.ajc.com/news/state–regional-govt–politics/court-upholds-ruling-for-third-party-presidential-candidates/hKV5eClapgz7Tgj3k6OK6N/
[3] http://ballot-access.org/2017/02/24/green-party-and-constitution-party-file-ballot-access-case-in-north-carolina/

by clinton at March 30, 2017 01:34 AM

March 16, 2017

Clinton Ebadi (clinton)

Some Parts of the Planet Don’t Suck

Good news for the Netherlands:

The big winner of Wednesday’s election – and now the largest party of the Dutch left for the first time – was GreenLeft, headed by 30-year-old Jesse Klaver, hailed by his enthusiastic supporters as the “Jessiah”.

Sometimes compared to Canada’s youthful prime minister, Justin Trudeau, Klaver – who has a Moroccan father and a mother of Indonesian descent – said on polling day that the left’s answer to the far right’s rise in Europe was to stand up for its ideals.
“What I would say to all my leftwing friends in Europe: don’t try to fake the populace,” he said.
“Stand for your principles. Be straight. Be pro-refugee. Be pro-European. We’re gaining momentum in the polls. And I think that’s the message we have to send to Europe. You can stop populism.”
The Netherlands’ youngest ever party leader, Klaver built a strong following on social media through small Meetup events after taking over GreenLeft’s leadership in May 2015.

by clinton at March 16, 2017 11:43 PM

March 15, 2017

Clinton Ebadi (clinton)

March 12, 2017

Clinton Ebadi (clinton)

Some Kind of Box

Something about blue teeth and video games.

panel box

by clinton at March 12, 2017 08:12 PM

February 24, 2017

Clinton Ebadi (clinton)

Angry Mobs At Town Halls

Where were these people when the Democrats scuttled socialized healthcare and gave us the capitalist abomination that is the ACA?

I think they were busy calling me a communist for suggesting that for-profit enterprise was intrinsically incompatible with a universally required service like “preventing people from dying on the streets.” But economic eugenics is ok — those poor undesirables really should have had a better lineage if they wanted healthcare after all — until the petit-privileged classes find out they too get to die on the streets as inequality rises.

And yet they still fight for their privileged capitalist healthcare (we just want the leeches to die, not proper middle class wage slaves, get it?) instead of fighting for something that would be unassailable when the forces of regression rise to attack again.

by clinton at February 24, 2017 12:28 AM

February 18, 2017

Clinton Ebadi (clinton)

February 15, 2017

Clinton Ebadi (clinton)

February 05, 2017

Clinton Ebadi (clinton)

February 04, 2017

Clinton Ebadi (clinton)

155 Lines

The CCFL backlight on my six year old monitor started having problems cold starting this week and I need my monitor to live so a new one was ordered. This was surprisingly cheap, QHD, and the included stand rotates which is neat for pdfs and viewing a ton of code at once (actual readable size here, could knock it down one point of I got around to getting new glasses). A few hours later I realized I could also play pinball on it… how did I live before?

by clinton at February 04, 2017 02:25 AM

Open Letter to Senator Thom Tillis: Kindly Go Fuck Yourself

Thom Tillis is a total asshole and should probably go fuck himself. His current views represent a disdain for democracy and education and I hope that he loses re-election and is banished from the public sphere for all of time when his seat comes up.

Here is a letter I wrote to him on the topic of the DeVos nomination after hearing he was on the fence and wanted the input of his constituents. Not that I thought it would do anything — I’ve far too good an education to think something like lobbying your representatives will result in representation, unless that lobbying comes with cash money or a promise of a lavish consulting gig later.

Greetings,

I recently read in the Charlotte Observer that you were seeking the input of North Carolina citizens in order to make your decision on the confirmation of DeVos for Secretary of Education. Since you asked — here’s my two cents:

Our public education system has been under attack by regressive anti-intellectual forces for decades, and her appointment represents their ultimate victory in their quest to build a compliant, uneducated populace. It would be a great tragedy to see our public education system completely dismantled for a system of second-rate charter schools (as can be seen from the many scandals with poor performance, grade inflation, and outright noncompliance with state education standards here in North Carolina), wherein only the privileged few may receive a good education while the rest languish in ignorance and the resulting lack of economic and social opportunity. It could very well result in the dissolution of the already tenuous social fabric itself in ten or twenty years time when the children of today take the helm of society. Now is the time to rebuild our failing system, not to encourage it to completely fail.

As representative democracy is based upon an informed and educated electorate, this would represent a great tragedy and an acceleration of our descent into status as a failed democracy. I exhort you to vote against her confirmation.

by clinton at February 04, 2017 12:07 AM

February 03, 2017

Clinton Ebadi (clinton)

Georgia Ballot Access Laws (Mostly) Overturned

One thing that bothers me about Democrats and their self-praise in regards to voting rights is that they have done more than the Republicans to suppress ballot access by third parties. Not that the Republicans haven’t done their fair share (it benefits both ol’ boys after all). There’s some good news on that front today: The 11th Circuit of Appeals upheld that Georgia’s Egregious and Unconstitutional Ballot Access Laws Are Indeed Unconstitutional:

The one-sentence ruling, by a unanimous three-judge panel of the 11th U.S. Circuit Court of Appeals, adopted the “well-reasoned opinion” issued last March by U.S. District Judge Richard Story in Atlanta. Story had significantly lowered the number of signatures required for third-party candidates to petition to get on Georgia’s presidential ballot — from tens of thousands [approximately 51k] to 7,500.

The ruling has a nice side-effect in that it lifts restrictions in Florida as well that curiously enough went unenforced from 2011 until August of 2016, just in time to keep “…Gloria La Riva, Evan McMullin, and Thomas Hoefling off the Florida ballot, with no warning.”

Georgia appears to be planning an appeal; my hope is that the Supreme Court will take up the case and strike down absurd ballot access restrictions across the country so that we can have freer elections in 2018. I mean, who cares if you can vote, if you have no options at the ballot box?

by clinton at February 03, 2017 12:13 AM

January 31, 2017

Clinton Ebadi (clinton)

Adventures in Syndication

I have a seemingly trivial task at hand: automagically repost things on the ol’ weblog from my public tt-rss atom feed. Just an excerpt and maybe a relevant picture, nothing too difficult.

I’ve been fighting it on and off again for years, recently finding cybersyn which worked but has its own bugs (like not aggregating anything without a valid thumbnail and filling my media library with gigantic stls from planet reprap. Still, it was the only one that actually fetched feeds with any reliability.

But to get excerpts and some other things I’ve had to hack it up… and have come to realization that I too must write another half-assed aggregation plugin. Or convince the cybersyn folks to add some filters to make it easier to munge things. Unfortunately that doesn’t fix things like it using php’s built in horror show of an xml parser (so I end up with feeds entitled “Article Title – Source Name” and there’s nothing I can do about — it’s just blindly catenating the title in <entry> and <source>, and the source comes last so that’s that without major surgery…

Running tests with my hacked up plugin set to post privately also reveals a social issue: I can easily share more than a full page of links in between real posts (if I actually journalled into the abyss… which I might be now). Thinking there should be some kind of squashing (e.g. everything posted in a 3h window gets thrown into one post). Or maybe not, tracking posts would be more annoying then. Trying not to think too hard about it and just get something minimal running soon.

by clinton at January 31, 2017 01:09 AM

January 30, 2017

Clinton Ebadi (clinton)

The Fight Against Fifteen

polticians / shitheads

Last week, the Montgomery County Council approved a bill that would have made it the first jurisdiction in Maryland — and the second in the region after Washington, D.C., to mandate a $15-per-hour base pay by 2020.

Del. Derek E. Davis (D-Prince George’s), the chairman of the House Economic Matters Committee, has introduced a bill that would put the General Assembly in charge of setting minimum wage even for cities and counties.
Davis said the bill would help improve the business climate in Maryland by making wage and benefit rules more predictable and consistent, noting that Montgomery and Prince George’s counties current have their own minimum-wage laws in place, and Baltimore considered a $15 base wage last summer.
“We’re not a collection of 24 individual fiefdoms,” Davis said “We have to work together as a state so we can attract and retain businesses, keep a healthy, strong economy, and not put our jobs at risk.”

Who needs Republicans when you have Democrats like these. It’s not like a higher minimum wage is a majoritarian viewpoint or anything like that…

by clinton at January 30, 2017 08:42 PM

January 29, 2017

Clinton Ebadi (clinton)

Zoom

This post brought to you by me finally overcoming extreme procrastination and general laziness and implementing fastcgi php support in domtool. Yep, we were spawning an independent php-cgi for each request…

by clinton at January 29, 2017 03:44 AM

January 28, 2017

Clinton Ebadi (clinton)

January 27, 2017

Clinton Ebadi (clinton)

Medicare For All

January 25th

A national physicians group today hailed the reintroduction of a federal bill that would upgrade the Medicare program and swiftly expand it to cover the entire population, saying it’s the only workable and equitable way to move forward in U.S. health care.

The Expanded and Improved Medicare for All Act, H.R. 676, introduced last night by Rep. John Conyers Jr., D-Mich., ranking member of the Judiciary Committee, with 51 other House members, would replace today’s welter of private health insurance companies with a single, streamlined public agency that would pay all medical claims, much like traditional Medicare works for seniors today.

And yet, not a peep from the so-called “Real Media”. Shocking. This broke January 20th, and aside from an open letter published by Ralph Nader, some press releases from physicians groups, and a few recent endorsements from labor unions the supposedly Liberal Media™ hasn’t made a peep. How can anyone fight for something they don’t know exists?

by clinton at January 27, 2017 08:48 PM

January 26, 2017

Clinton Ebadi (clinton)

May 17, 2016

Sajith Sasidharan (sajith)

Yosemite, the Barn

2016-04-28-20-40-13-yosemite.jpg

I've been reading A Supposedly Fun Thing I’ll Never Do Again: Essays and Arguments, by our dear departed author, David Foster Wallace. One of the essays, E unibus pluram: television and U.S. fiction (1993) dissects mainstream intelligentsia's generally-agreed habit of looking down upon the television watching masses, and television itself, with contempt and ridicule.

(I guess it was dissection, because I am unable to grasp the essay entirely. I simply do not have enough context. What was I doing in 1993? Not watching television, not ridiculing TV-watching habits of the masses, not reading intelligentsia-on-TV take-downs, for sure.)

In the essay, Wallace quotes Don Delillo (Delillo's 1985 novel, White Noise, specifically), "a long-underrated conceptual novelist who has made signal and image his unifying topoi":

Several days later Murray asked me about a tourist attraction known as the most photographed barn in America. We drove twenty-two miles into the country around. Farmington. There were meadows and apple orchards. White fences trailed through the rolling fields. Soon the signs started appearing. THE MOST PHOTOGRAPHED BARN IN AMERICA. We counted five signs before we reached the site…. We walked along a cowpath to the slightly elevated spot set aside for viewing and photographing. All the people had cameras; some had tripods, telephoto lenses, filter kits. A man in a booth sold postcards and slides—pictures of the barn taken from the elevated spot. We stood near a grove of trees and watched the photographers. Murray maintained a prolonged silence, occasionally scrawling some notes in a little book.

“No one sees the barn,” he said finally.

A long silence followed.

“Once you’ve seen the signs about the barn, it becomes impossible to see the barn.”

He fell silent once more. People with cameras left the elevated site, replaced at once by others.

“We’re not here to capture an image. We’re here to maintain one. Can you feel it, Jack? An accumulation of nameless energies.”

There was an extended silence. The man in the booth sold postcards and slides.

“Being here is a kind of spiritual surrender. We see only what the others see. The thousands who were here in the past, those who will come in the future. We’ve agreed to be part of a collective perception. This literally colors our vision. A religious experience in a way, like all tourism.”

Another silence ensued.

“They are taking pictures of taking pictures,” he said.

And what did DFW think of the text he quoted?

I quote this at such length not only because it’s too good to edit but also to draw your attention to two relevant features. One is the Dobyns-esque message here about the metastasis of watching. For not only are people watching a barn whose only claim to fame is being an object of watching, but the pop-culture scholar Murray is watching people watch a barn, and his friend Jack is watching Murray watch the watching, and we readers are pretty obviously watching Jack the narrator watch Murray watching, etc. If you leave out the reader, there’s a similar regress of recordings of barn and barn-watching.

But more important are the complicated ironies at work in the scene. The scene itself is obviously absurd and absurdist. But most of the writing’s parodic force is directed at Murray, the would-be transcender of spectation. Murray, by watching and analyzing, would try to figure out the how and whys of giving in to collective visions of mass images that have themselves become mass images only because they’ve been made the objects of collective vision. The narrator’s “extended silence” in response to Murray’s blather speaks volumes. But it’s not to be taken as implying sympathy with the sheeplike photograph-hungry crowd. These poor Joe Briefcases are no less objects of ridicule for the fact that their “scientific” critic is himself being ridiculed. The narrative tone throughout is a kind of deadpan sneer, irony’s special straight face, w/ Jack himself mute during Murray’s dialogue—since to speak out loud in the scene would render the narrator a part of the farce (instead of a detached, transcendent “observer and recorder”) and so himself vulnerable to ridicule. With his silence, DeLillo’s alter ego Jack eloquently diagnoses the very disease from which he, Murray, barn-watchers, and readers all suffer.

The points I'm trying to make here are far more simple: (1) we visited National Park in the last week of April, and (2) I do not think I have seen such a confluence of photographers anywhere else. NPS properties all over America have their share of people with fancy and expensive cameras, all the time. Yosemite simply appears to have has more of them.

I do not believe that there's anything wrong or objectionable to there being such a confluence of people that enjoy taking pictures. Or a confluence of people that enjoy whatever creative or non-creative pursuits that they are pursuing. Some of my very good friends are photographers! I might be one myself, if you squint the right way.

Nevertheless, the DeLillo quote quote made me feel morally superior for a brief moment (in an us-vs-them, "ah look at all these ridiculous people with cameras!" way), and after a moment of pause, rather quite uncomfortable (in an "Oh no, I myself am one of them!" way).

I was only vaguely aware that photography, among other popular pursuits, was subjected to some amount of contempt by certain class of intellectuals. I chose to ignore it, until the above-quoted piece made things clear to me.

I will admit that Wallace's counter-take has soothed me somewhat.

• • •

Anyway, now that I've been made acutely aware of it, here are some of my ridiculously touristy pictures from Yosemite National Park.

2016-04-28-20-09-40-yosemite.jpg

2016-04-28-20-41-51-yosemite.jpg

2016-04-28-20-56-16-yosemite.jpg

2016-04-28-20-57-17-yosemite.jpg

2016-04-29-18-12-28-yosemite.jpg

2016-04-29-20-25-30-yosemite.jpg

Prior to visiting Yosemite, we spent a week in San Francisco, where both of us fell sick. Consequently I could not meet some of the friends I wanted to meet, and my plan to go see the Computer History Museum in Mountain View fell flat. For the most part of two days, I was stuck in a hotel room, moving my runny nose between bathroom and bed.

However! I would like to report that we still made it to Yosemite, and climbed all the way up to Upper Yosemite Falls and then Yosemite Point (8.2 miles round-trip, all ascent and descent), huffing and panting, coughing and wheezing and sneezing.

We perhaps were the slowest hikers in that particular trail. It was still worth the trouble. It was pretty memorable.

And I've taken some pictures.

May 17, 2016 05:00 AM

April 13, 2016

Daniil Frumin (notd)

Frobenius property of weak factorisation systems and Pi-types

I’ve put together a note on the Frobenius property for weak factorisaion systems and it’s relation to models of type theory. Awodey and Warren described a way of obtaining a model of type theory with identity types from a model category structure/weak factorisation system. However, in absence of axioms for other type formers (specifically, Π-types), one is required to put an additional restriction on the weak factorisation system, in order to model identity elimination in an arbitrary context/with arbitrary parameters; specifically, it is required that cofibrations are stable under pullbacks along fibrations. In presence of Π-types, however, this is not necessary, as I tried to explain in the note.


Tagged: category theory, type theory

by Dan at April 13, 2016 08:56 AM

March 20, 2016

Sajith Sasidharan (sajith)

A Tale of Two Winters

2015-02-14-14-05-51-chesterton.jpg

Last year in the second week of February, we went to Indiana Dunes State Park to gawk at the ice shelves that were formed on Lake Michigan. The ice shelves laid sprawled out on top of the frozen lake, but we could not quite approach it, much less gawk at it – howling winds that nearly sandblasted us came between us and the lake. The wind blasted a lens away from an eyeglass. On our way home, we were stuck in a massive, wild, yet beautiful lake effect blizzard for many hours. Many vehicles laid on either side of the road, skidded this way or that way because the road was hardly visible, with people inside, waiting for assistance. Amidst the storm, a passing good Samaritan spotted the flat tire on our tiny hatchback, perhaps just in time before it led to something far worse.

• • •

2016-02-07-04-37-40-dunes.jpg

This year we went back there in the first week of February. Lake Michigan looked rather quite placid this time. We went at sunset, and again at sunrise, and took walks on the lake shore. It was cold, but there were no ice shelves. This year's winter has been indeed relatively milder.

• • •

I can't quite decide which way I like it. I think I like the early arrival of spring.

March 20, 2016 05:00 AM

November 15, 2015

Sajith Sasidharan (sajith)

Fall Park Hopping

I am not quite sure I was really planning on it, but I seem to have spent nearly five years in the North American continent by now. In spite of that, and to my mild embarrassment, I still haven't witnessed the famed autumn foliage of north America where it is celebrated most – most of New England, or the Great Smoky Mountains National Park of Tennessee and North Carolina, or the Pocono Mountains of Pennsylvania, or the Rocky Mountain Region of Colorado, or Yosemite National Park of California, or Grand Teton National Park of Wyoming, or Denali National Park of Alaska, or Glacier National Park of Montana, or Shenandoah National Park of Virginia. Or Cuyahoga Valley National Park of Ohio, or Michigan's upper peninsula – both of which aren't that far from where I am.

Truth be told, I haven't seen most of them even otherwise. This is a huge country, and traveling takes time, money, and effort. Who but the most privileged have these things in abundant supply? I guess I will see these wonders when I see them. I am not big on making plans anyway.

In any case, I do not have to worry too much about my lack of exposure to fall foliage! Because even humble Indiana puts up a respectable autumn show. We tried to catch up a bit, and here are some pictures to show for it.

• • •

Pokagon State Park is near Angola, Indiana – about an hour or so from home, more if you take the country roads. Country roads are great with none of the rush and din and impatient drivers of highways. You must take them on your leisurely trip to observe fall foliage. For maximum leisureliness, you must take the time to visit the coffee shop in Angola town center and drink their coffee and taste their pies.

2015-10-17-16-39-24-pokagon.jpg

2015-10-17-16-51-16-pokagon.jpg

2015-10-17-17-00-29-pokagon.jpg

2015-10-17-17-04-21-pokagon.jpg

• • •

Chain O' Lakes State Park is less than an hour from home. Thankfully there are no highways leading there. The big attraction here are the nine connected lakes. The friendly DNR (Indiana Department of Natural Resources) staff will rent you boats and paddles for a small fee. Or bikes, if that is your thing.

(The other big attraction for us is a farmer's house near the park. They sell eggs on a honor system – you take eggs, you leave money. We have never seen the human owners around, but the hens are always around. Thank you hens and their humans! Those are are some of the freshest and most delicious eggs we have ever tasted.)

2015-10-18-17-21-29-chain-o-lakes.jpg

2015-10-18-17-42-25-chain-o-lakes.jpg

2015-10-18-17-39-28-chain-o-lakes.jpg

• • •

Lindenwood Nature Preserve is a relatively modest affair: 110 acres or so of wooded area, with a small lake in the middle. The preserve is managed by the City of Fort Wayne, and, quite conveniently, it is within the city. Sadly the preserve closes at the end of fall season, to reopen in the spring.

(Right next to the preserve lies Lindenwood Cemetery, another 175 acres of strolling space that also happens to be open year-round – if you feel like finding peace amidst the dead, year-round.)

2015-10-24-16-12-23-lindenwood.jpg

2015-10-24-15-59-33-lindenwood.jpg

2015-10-24-15-41-17-lindenwood.jpg

2015-10-24-16-13-26-lindenwood.jpg

• • •

Fox Island County Park is just nine miles from home. Given the shortness of the drive there, and pleasantness of the place, it would seem that we don't appreciate it enough. We planned on going swimming in the lake there in the summer – a plan that did not actually materialize, as you might suspect. See you one of these summers, lake!

2015-11-03-16-46-42-fox.jpg

2015-11-03-17-09-10-fox.jpg

2015-11-03-17-18-16-fox.jpg

• • •

You know what? It seems that a person can be quite content with these small yet priceless pleasures, without having gone anywhere great or famous. I am grateful for these places, and the people and the agencies that maintain them so well.

November 15, 2015 06:00 AM

November 03, 2015

Sajith Sasidharan (sajith)

Internet Relay Chat

I have been /away from IRC for such a long time. I am a terrible person for that reason, and very many other reasons. However, unlike me, my IRC client, safely and warmly tucked under a layer of old and wrinkly screen session, has been faithfully listening to a handful of channels on freenode.

Today I felt like checking the aforesaid IRC client for any missed messages, and found a rather old /query window. It went like this:

03:23 -!- Irssi: Starting query in freenode with Guest33674
03:23 <Guest33674> Hello. i'm eRic M France. I'm there to share
                   information concerning theories about our
                   origins. Monotheism & Evolution's theory are 
                   based on beliefs 'cause nothing in science can 
                   establish that these théories are correct
03:23 <Guest33674> However, the new one considering that we have
                   been created by human beings of a most advanced
                   civilisation mastering biotechnologies 
                   (intelligent Design) is enlightened with real 
                   facts. Wanna read about it ?
Day changed to 26 Jun 2015
Day changed to 27 Jun 2015

[...]

Day changed to 02 Nov 2015
Day changed to 03 Nov 2015

That was not the only one. Another /query window went like this:

23:52 -!- Irssi: Starting query in freenode with jimmiejohnson48
23:52 <jimmiejohnson48> I just wanted to make sure you go to heaven
                        when you die, the bible says nobody is good
                        enough to make it to heaven, so we need to
                        believe on Jesus in order to make it to
                        heaven! Google "Jesus is savior" and click
                        how to be saved, and keep in mind IF SAVED
                        YOU'RE ALWAYS SAVED salvation can NOT be 
                        lost, it is a FREE GIFT of God! Also watch
                        this preacher www.youtube.com/watch?v=-qspZSTV5uY 
                        Hope
23:52 <jimmiejohnson48> you believe on the Lord because that is all
                        we are required to do, not do good works or 
                        give up our sins, that's a damnable plan of
                        salvation which is all explained on that
                        website. I also wanted to tell you that
                        nothing is better than Jesus I tried it all
                        fast cars, relationships, liquor, nothing
                        filled the empty void I had and that was
                        having a personal relationship and knowing
                        the one who
23:52 <jimmiejohnson48> still has nail scars in his hands and side
                        to this day and forever will! You can take
                        my word for it or go try all the pleasures
                        of the world, but if you choose Jesus later 
                        and have a false plan of salvation you won't
                        get into heaven, so getting saved now is a 
                        good idea!
Day changed to 06 Jul 2015
Day changed to 07 Jul 2015

[...]

Day changed to 02 Nov 2015
Day changed to 03 Nov 2015

You can imagine my dismay and regret on having missed these excellent opportunities to learn about the mysteries of our world and the secret to a sure place in heaven from those two seemingly wonderful persons.

I wonder if eRic M France is still up for offering pedagogical services on his particular school of thought, and if jimmiejohnson48 still cares about my salvation. IRC is a weird place for all this, but whatevs. It is not their fault that I don't use facebook or whatsap or whatever it is that normal people use for such casual-yet-ascendant communication these days.

But mainly I am impressed that knowledge has chosen to seek me out. It must be because the other way around is not working as well as it should be.

Maybe salvation is within reach, when all said and done.

November 03, 2015 06:00 AM

October 06, 2015

Clinton Ebadi (clinton)

September 24, 2015

Daniil Frumin (notd)

Darcsden improvements and Darcs sprint

This post is intended to be a short summary of my SoC project, as well as my recent trip to Darcs sprint.

Introduction

I am finishing up this post on the train back from the Autumn 2015 Darcs sprint. Today (Sept 20, Sun) was a very fun day full of darcs chatting and coding. By the end of the day we’ve heard a number of presentations

  • Ganesh described his work on "stash" command for darcs (naming subject to change!). It involves some refactoring of the rebase code. I hope we would hear more from him on that, because the internal workings are actually quite interesting — I believe it’s the first time singleton types and DataKinds are used in the darcs codebase;
  • Florent Becker gave a presentation about Pijul and the theory behind it — A Categorical Theory of Patches by Samuel Mimram and Cinzia Di Giusto, see arXiv:1311.3903;
  • Vinh Dang talked about his improvements on the darcs wiki (it’s about time to organize the website), his goal was to make it more accessible to the newcomers;
  • Yours truly gave a small presentation, outline of which you will find below:

Looking back

I have spent this summer hacking on DarcsDen as part of the Google Summer of Code program.

My basic goal was to create a "local" version of darcsden. It was not a trivial task to install darcsden (and probably installation is still not very easy!). It uses a third-party software like Redis and CouchDB. During my coding process I modifed darcsden such that it now can be a good choice for local (or lightweight single user) darcs UI. The local darcsden version can be used without any databases, tracking the repositories in the local file system. This way darcsden can be used by a developer on her local computer, like darcsum, (for working with/comparing repositories) as well as a replacement for darcsweb/cgit — a single user web front for darcs repositories.

Besides that a user of a local version can use darcsden’s interactive UI for recording new patches, as well as a command-line tool den for a quick way of browsing the repositories.

Installing darcsden-local is currently not as easy as I want to it be, but I hope that soon you will be able to install it just by running cabal install darcsden or brew install darcsden. As for now, one could do the following:

  1. darcs get --lazy http://hub.darcs.net/co-dan/darcsden-local
  2. cabal install . or stack install

This should install the darcsden binary and all the related css/js files. You can start darcsden by running darcsden --local. If you open your web browser you should see a list of repositories in the current directory.

However, you might have repositories scattered all over the place, and scanning your whole system for darcs repositories is just inefficient. For this purposes darcs keeps a list of repositories in a file inside your ~/.darcs directory. You can manage that list either by hand, or using the command-line den tool:

  • den $PATH — add $PATH to the list of repositories in ~/.darcs/darcsden_repos (if it’s not already present there), start darcsden server in the background and launch the browser pointing to $PATH;
  • den — the same as den .;
  • den --add $PATH — add $PATH to the list of repositories in ~/.darcs/darcsden_repos;
  • den --remove $PATH — remove $PATH from the list of repositories in ~/.darcs/darcsden_repos.

In order to further customize darcsden, one can tweak the configuration file located at ~/.darcs/darcsden.conf. Apart from the usual darcsden settings one may pay attention to the following variables:

  • homeDir (default .), points to the "root" directory with repositories. If the list file ~/.darcs/darcsden_repos is not present darcsden will recursively search repositories in that directory
  • unLocal, pwLocal: the username and the password of the "local" user

The user/password credentials are required for editing the repositories and recording new patches. However, the den binary should automatically pick them up from the config file and log you in.

Once you are logged in, and you have unrecorded changes in the repository, you can use darcsden UI to record a new patch.

DarcsDen record

DarcsDen record

Below you can see an example of recording and merging patches from a branch.

DarcsDen merge

DarcsDen merge

Darsden allows you to create forks/branches of your repositories, and it keeps track of the patch dependencies in your branches.

More "internal" changes:

  • Instead of having to specify some parts of the configuration in DarcsDen.Settings, darcsden now uses runtime flags: –hub for using hub-specific modifications, –local for using the local backend and no flag for default behaviour
  • The flag actually choose what are called instances — something that a bit less fine-grained than settings. Instances allow you to pick backend, overwrite settings, modify the looks of the front page.
  • HTTP-testing using wreq. The previous test suite used selenium and it got bit-rotten. The wreq-based is easier to run and perhaps slightly easier to maintain.
  • HTTP auth, which is used as part of the local instance; the den tool utilizes it to log the user in automatically.
  • Support for repositories inside directories and nested repositories.
  • All the backend code that is used for handling repositories and meta-data on the file system.
  • Functionality for downloading zipped dist archives of darcs repositories.
  • Assorted mini-fixes

What now?

During the sprint I hacked together some code for viewing suspended patches along the regular ones. The next step would be to have a similar interface for managing the suspended patches.

We have also discussed the possibility of adding rewrite rules implementing short-cut fusion for the directed types in Darcs. In order to see if it’s really worth it we would have to bring back to life the benchmarking suite (or at least check on it!).

It was a really exciting weekend for me and I was delighted to meet some of my IRC friends. As it turns out, it is a small world and despite being from different parts of it we have a bunch of common IRL friends, professors. As the French would (probably not) say, très bien. The next darcs sprint will probably be in January, and probably in Europe, again.


Tagged: darcs, haskell

by Dan at September 24, 2015 12:38 PM

September 20, 2015

Daniil Frumin (notd)

Darcs internals, part 1: typesafe directed datastructures

I am editing this post from IRILL, where the darcs sprint is taking place

One of the things that I particularly like about the Darcs codebase is that you can see that the developers were not shy about using intermediate-slash-advanced Haskell/GHC features to help achieving type safety. You can see GADTs, associated types, phantom types, existential types actively used.

In this post I would like to discuss the representation of patches and the use of type witnesses in darcs.

A word about patches and contexts

This post is intended for people interested in patch theory and its implementation in darcs. A passing familiarity with patches, contexts, inverses, etc is useful, but not required, as we restate some basic definitions in this section.

A primitive patch is a basic unit in patch theory. It constitutes an atomic change in the repository. The definition of a primitive patch may vary, but usually the following changes are considered primitive patches:

  • Removing a file from the repository
  • Adding file to the repository
  • Changing a line n in a file in the repository
  • Identity patch, i.e. an empty/non-existing change that does not modify the state of the repository at all

Every primitive patch has a pre-context and a post-context. Roughly, you can think of a pre-context as the full state of the repository before the change was made, and of the post-context as the full state of the repository after the change was applied. We write (x)-A->(y) for a patch A with a pre-context x and a post-context y.

If a primitive patch A has a pre-context a, a post-context o, and a primitive patch B has a pre-context o, a post-context b, then we can combine two patches to obtain a sequential patch AB with the pre-context a and the post-context b.

Every primitive patch (x)-A->(y) has an inverse (y)-A^{-1}->(x), such that (x)-A->(y)-A^{-1}->(x) is equivalent to the identity patch (x)-1->(x).

In the next sections we will see how those things are implemented in darcs.

Primitive patches and witnesses

A primitive patch, which constitutes a single fine grained change, can be represented as a (G)ADT:

data Prim where
    Move :: FileName -> FileName -> Prim
    RmFile :: FileName -> Prim
    AddFile :: FileName -> Prim
    Hunk :: FileName -> Int -> ByteString -> ByteString -> Prim
    RmDir :: FileName -> Prim
    …

We can represent complex patches as sequences of primitive patches:

data Patch where
    NilP :: Patch
    PrimP :: Prim -> Patch
    SeqP :: Patch -> Patch -> Patch

This seems reasonable enough. But if we implement our patch theory this way we seem to be missing something — patches have (pre- and post-) contexts. Having contexs allows us to enforce patch composition on the level of type system. Consider the following definition, which uses phantom types as type witnesses for contexts.

data Prim x y where
    Move :: FileName -> FileName -> Prim x y
    RmFile :: FileName -> Prim x y
    AddFile :: FileName -> Prim x y
    Hunk :: FileName -> Int -> ByteString -> ByteString -> Prim x y
    RmDir :: FileName -> Prim x y
    …

data Patch x y where
    NilP :: Patch x x
    PrimP :: Prim x y -> Patch x y
    SeqP :: Patch x y -> Patch y z -> Patch x z

We call the types with witnesses representing pre- and post-contexts directed types. Intuitively, the directed type D x y has a “direction” from x to y, written as (x)->(y). The Prim datatype looks pretty much like the type actually used in Darcs. The Patch datatype, however, is completely artificial. We will see in the next sections how Darcs really models complex patches.

Directed programming

FL & RL

Two particularly useful directed types used in darcs are directed lists: forwards lists of the type FL a x y and reverse lists RL a x y. Forward lists “go” from the head to the tail; reverse lists “go” from the tail to the head. The lists are polymorphic over a just like regular lists.

data FL a x y where
    NilFL :: FL a x x    {- The empty list stays at (x) -}
    (:>:) :: a x y -> FL a y z -> FL a x z
infixr 5 :>:

For myself, I visualise forward lists like this:

(x) —a—> (y) —b—> (z) ——Nil——> (z)
a :: Patch x y
b :: Patch y z
(a :>: b :>: NilFL) :: FL Patch x z

The reverse lists are “going” from tail to head1

data RL a x y where
    NilRL :: RL a x x
    (:<:) :: RL a x y -> a y z -> RL a x z
infixl 5 :<:

(Mnemonically, the the head is always “greater” than the tail)

The reason I used the word “go” inside quotation marks so far is the following. Reverse lists and forward lists represent the same concept: a sequence of patches (or a sequence of directed things for that matter). They only differ in the associativity of the elements. Forward lists associate to the right, but reverse lists associate to the left.

p = Move "foo" "bar"

-- [[(x) --Nil--> (x) -p-> (y)] -id-> (y)] -p^{-1}-> (x)
example :: RL Patch x x
example = NilRL :<: p :<: Identity :<: inverse p

-- (x) -p-> [(y) -p^{-1}-> (x) --Nil--> (x)]
example2 :: FL Patch x x
example2 = p :>: inverse p :>: NilFL

The right-associated/reverse lists provide easy access to the last element of the sequence; the left-associated/forward lists provide easy access to the first element of the sequence. Therefore, if we view a repository as a directed sequence of patches, right-associated lists are useful for operations that work on the “latest” patches in the repository (such as record/unrecord), and left-associated lists are useful for commands that scan the repository from the beginning (like clone).

We can reassociate the lists easily, and verify that the two representations are isomoprhic:2

reverseRL :: RL a wX wY -> FL a wX wY
reverseRL = r NilFL
-- the type signature of r basically gives us an invariant
-- wZ is slowly "decreasing" reaching the point where
-- wZ = wX; at that point the first argument is of type FL a wX wY
  where r :: FL a wZ wY -> RL a wX wZ -> FL a wX wY
        r a NilRL = a
        r a (xs :<: x) = r (x :>: a) xs

For example,

-- [[(x) --Nil--> (x) -p-> (y1)] -q-> (y2)] -r-> (z)

Turns into

-- (x) -p-> [(y1) -q-> (y2) -r-> [(z) --Nil--> (z)]]

Exercise: write a function reverseFL :: FL a wX wY -> RL a wX wY

We can write a lot of directed analogues of familiar list functions. For example, here is a directed append:

infixl 5 +<+
(+<+) :: RL a wX wY -> RL a wY wZ -> RL a wX wZ
xs +<+ NilRL = xs
xs +<+ (ys :<: y) = (xs +<+ ys) :<: y

Exercise: write directed append for forward lists: (+>+) :: FL a wX wY -> FL a wY wZ -> FL a wX wZ

Type witnesses

So we wrote a bunch of standard list functions for directed lists; what about some of the other functions? Can we, for example, implement filter for directed lists. Can it look like filterFL :: (a wX wY -> Bool) -> FL a wX wY? Well, we can try writing

filterFL :: (a wX wY -> Bool) -> FL a wX wY
filterFL p NilFL = NilFL
filterFL p (x :>: xs) | p x = filterFL p xs
                      | otherwise = x :>: filterFL p xs

However, under closer scrutiny we realize that it does not typecheck! In the second clause of filterFL we have the following information:

x :: a x y, xs :: FL a y z
filterFL xs :: FL a y z

Thus, in the first case (in which p x holds) we try to return something of the type FL a wY wZ, when FL a wX wZ was expected. It is clear that generally we can do this only if x :: a wX wX, i.e. wY = wX. But a simple predicate of the type p :: a wX wZ -> Bool won’t tell us anything about that. We need an additional type witness in our system telling us that if p x holds, then x :: a wX wX. For that purpose we introdue the EqCheck datatype.

data EqCheck wX wY where
    IsEq :: EqCheck wX wX
    NotEq :: EqCheck wX wY

then the type of a predicate would be

type Pred a = forall wX wY. a wX wY -> EqCheck wX wY

If (p x) = IsEq, then the typechecker will know that x :: a wX wX. We can then finally write

filterFL :: Pred a -> FL a wX wY -> FL a wX wY
filterFL p NilFL = NilFL
filterFL p (x :>: xs) | IsEq <- p x = filterFL p xs
                      | otherwise   = x :>: filterFL p xs

EqCheck is used this way in the darcs source code to e.g., filter our internal patches. Sometimes darcs stores information — like suspended patches — in the so called internal patches. Every patch type implements the internal patch checker (code slightly adapted):

-- |Provides a hook for flagging whether a patch is "internal" to the repo
-- and therefore shouldn't be referred to externally, e.g. by inclusion in tags.
-- Note that despite the name, every patch type has to implement it, but for
-- normal (non-internal) types the default implementation is fine.
-- Currently only used for rebase internal patches.
class MaybeInternal p where
    -- | @maybe (const NotEq) (fmap isInternal patchInternalChecker) p@
    -- returns 'IsEq' if @p@ is internal, and 'NotEq' otherwise.
    -- The two-level structure is purely for efficiency: 'Nothing' and 'Just (InternalChecker (const NotEq))' are
    -- semantically identical, but 'Nothing' allows clients to avoid traversing an entire list.
    -- The patch type is passed as an 'FL' because that's how the internals of named patches are stored.
    patchInternalChecker :: Maybe (forall wX wY . FL p wX wY -> EqCheck wX wY)
    patchInternalChecker = Nothing

When the user runs darcs tag in the repository, darcs creates a dummy patch that explicitly depends on all the previous patches — apart from the internal ones of course. Thus, the tag command uses the following function (slightly adapted):

filterNonInternal :: MaybeInternal p => PatchSet p wX wY -> PatchSet p wX wY
filterNonInternal =
  case patchInternalChecker of
     Nothing -> id
     Just f -> \l -> PatchSet (filterRL (f . patchcontents . hopefully) (unPatchSet l))

where a PatchSet is the list of PatchInfoAnd patches — patches together with the meta-information.

It is worth noting that EqCheck x y is isomorphic Maybe (x :~: y), but the propositional equality datatype has only been added to base since 4.7.0.0. In the future versions darcs will probably switch to using Data.Type.Equality.

Conclusion

We’ve briefly touched upon patch representation in darcs and talked about directed types and directed programming.

A good if a bit outdated reference is Jason Dagit’s master thesis (specifically the bits from chapter 4). The wiki is currently lacking in material, but I hope to improve the situation eventually.

Next time we will probably discuss either directed pairs and their use in darcs, or sealed datatypes, or both.


  1. Essentially, a reverse list is a directed version of a snoc-list.

  2. Before darcs 2.10.1 the right-associated lists had a slightly different datatype, and for the old lists those functions would “reverse” the list. Hence the names of the functions.


Tagged: darcs, haskell

by Dan at September 20, 2015 10:20 AM

August 23, 2015

Clinton Ebadi (clinton)

More Packages Arrive

My 600W 24V DC power supply arrived from mouser, along with my hobbed bolts and the NEMA14 motors for the dual extruder.

I’m wiring up the DC side of the power supply to use 12 awg wire and female disconnects for now. I’ve got the main board supply, a separate line for the heatbeds, and a third set that will be wired in voltage regulator to give me a couple of amps of 12V power for the fans.

And, yeah, heatbeds. The Wilson y-axis can be stretched to 400mm, and I figured it was worth a shot going all the way. I wanted at least 300mm in the x-axis as well, and I found 200x300mm heatbeds (cheaper than one 300mmx300mm) and a conveniently sized 16″x12″ piece of glass at Home Depot. Worst case, it proves to be too large and I have to downgrade to 200mmx300mm (keeping the second heatbed ready for The Future™). This might seem a wee bit insane, but, after having used the TAZ 4, less than 300mmx300mmx250mm seemed underwhelming.

For the controller, I got an Azteeg X3 Pro because it has dual heatbed MOSFETs and support for up to five extruders as a bonus. At the outset, I decided to sink some of the savings over buying a printer into dual extrusion, and wanted to leave open the possibility of at least triple later on… and the X3 Pro wasn’t much more than a RUMBA with steppers aaaand it came with eight stepper drivers (useful in their own right), was fully soldered, and, hey… a triple nozzle extruder plus a single hexagon in the next couple of years or something doesn’t seem too crazy does it?

Not much I can do now until my nuts and bolts come Monday or Tuesday. I have very boring things to say about crimping wire harnesses too.

by clinton at August 23, 2015 06:42 AM

August 21, 2015

Clinton Ebadi (clinton)

I Guess I Actually Went Through With It

So I printed the parts for a three dee printer on a TAZ 4 my friend graciously let me borrow, and I may have actually spent weeks going over the BOM a few times … and ended up hitting order on a few too many websites. Packages started trickling in yesterday…

This is going to be … interesting.

by clinton at August 21, 2015 03:06 AM

August 14, 2015

Steve Killen (nevetski)

Open water

Things are officially As Real As It Gets–today I set up a life insurance policy for my wife and son. In the whirl of complexity that is our life, in the maddening press of all the things we are perceived as needing or actually need or are able to discern that we don’t need, this is one of the anchors, the failsafe in case the unthinkable happens. It very nearly did this past January in the form of a woman stopping dead in the midst of morning rush-hour traffic, and I am lucky to be alive. So I am not taking chances, not with our future already in such flux.

We are on the verge of being in open water, adrift on the ocean of our lives–to extend the metaphor, currently in dock at a safe harbor to bring our son into the world, so that he can swim with us. Mexico and South Korea are now equally viable candidates for our work, so we research them while I keep us afloat with gardening work. I just took care of the biggest major bill in our short term future, and we are paring down expenses and selling our needless possessions (rather a lot, it turns out). We don’t require much in the way of Things, mostly just the electronic tools to make sense of this modern world. So much ephemera, in the face of everything being ephemera–

“Like a tiny drop of dew, or a bubble floating in a stream; 
Like a flash of lightning in a summer cloud, 
Or a flickering lamp, an illusion, a phantom, or a dream.”
Diamond Sutra, Ch. 32

But how we make our way through this ephemera still matters. We can shape our son to make good choices, to change the world in his way, to better the lives of those around him just as I want to.

by Steve Killen at August 14, 2015 01:30 AM

July 28, 2015

Daniil Frumin (notd)

Darcs rebase by example

Darcs is a patch-centric version control system. In Darcs, there is no “correct” linear history of a repository – rather, there is a poset of patches. That means that most of the time you are pushing and pulling changes you can cherry-pick patches without a problem. However, in some cases you cannot perform a pull (or some other operation on the repository) smoothly. Sometimes it is necessary to rewrite the “history” – i.e. modify a patch that is a dependency of one or more other patches. For those cases darcs rebase comes in handy. To put it in the words of the implementor “Rebase is a workaround for cases where commutation doesn’t do enough”.

A repository can change it’s state from rebase-in-progress back to normal if there are no suspended patches left. However, be aware that you cannot unsuspend a patch1 if you have unrecorded changes in the repository. In light of this, I suggest recording a temporary patch with current changes

darcs record -am DRAFT

You can suspend that patch at the beginning of your rebase process and apply it at the end.

General overview of rebase

darcs rebase is an operation (or, rather, a family of operations) that allows one to make changes “deep down” in the repository history. One of the crucial things that allows for rebase to work is the fact that since darcs 2.10 patches can be suspended. When one performs any of the darcs rebase commands, the repository moves to a special rebase-in-progress state. In this state repository contains a pristine, a set of patches, a working copy, and — in addition to all the usual stuff — a set of suspended patches. Suspended patches are not active in the repository — that is, they are not applied.

Let’s go over the rebase subcommands

rebase log/rebase changes

This is simple: list the suspended patches

rebase suspend

Moves selected patches into the suspended state. Once the patch is suspended it is no longer active in the repository.

Note: once you suspend a patch, it changes its identity. That means that even if you suspend a patch and unsuspend it immediately, you will get a different repository that you have started with. Let this be a good reason (one of a couple!) for doing rebase on a separate branch.

> cat file
test
123
> darcs rebase suspend
	patch 64523bc4622fad02a4bdb9261887628b7997ebdd
Author: Daniil Frumin 
Date:   Thu Jul 23 18:49:30 MSK 2015
  * 123
Shall I suspend this patch? (1/5)  [ynW…], or ? for more options: y
patch cc54d7cf4b9e3d13a24ce0b1b77b76581d98d75d
Author: Daniil Frumin 
Date:   Thu Jul 23 18:43:53 MSK 2015
  * Test
Shall I suspend this patch? (2/5)  [ynW…], or ? for more options: d
Rebase in progress: 1 suspended patches
> darcs rebase log
patch 64523bc4622fad02a4bdb9261887628b7997ebdd
Author: Daniil Frumin 
Date:   Thu Jul 23 18:49:30 MSK 2015
  * 123
Shall I view this patch? (1/?) [yN…], or ? for more options: y
[123
Daniil Frumin **20150723154930
 Ignore-this: 43e09e6503ac74688e74441dc29bce25
] hunk ./file 2
+123
Rebase in progress: 1 suspended patches
> cat file
test

rebase unsuspend

Does the opposite of suspend: applies a suspended patch to the repository and changes its state to normal.

> darcs rebase unsuspend                                                                                       
patch 64523bc4622fad02a4bdb9261887628b7997ebdd
Author: Daniil Frumin 
Date:   Thu Jul 23 18:49:30 MSK 2015
  * 123
Shall I unsuspend this patch? (1/1)  [ynW…], or ? for more options: y
Do you want to unsuspend these patches? [Yglqk…], or ? for more options: y
Rebase finished!

rebase apply

Rebase apply takes a patch bundle and tries to apply all the patches in the bundle to the current repository. If a patch from the bundle conflicts with a local patch, then the local patch gets suspended. You will thus have a chance to resolve the conflict by amending your conflicting patches, at a price of.. well, changing the identity of your local patches.

rebase pull

Sort of like rebase apply, but instead of a patch bundle it obtains the patches from a remote repository.

Specifically, rebase pull applies all the remote patches, one-by-one, suspending any local patches that conflict. We will see more of rebase pull in the second example.

Example 1: suspending local changes

Imagine the following situation: at point A you add a configuration file to your repository, then you record a patch B that updates the settings in the configuration file. After that you make some more records before you realize that you’ve included by accident your private password in patch A! You want to get rid of it in your entire history, but you can’t just unrecord A, because B depends on A, and possibly some other patches depend on B.

The contents of the configuration file after patch A:

port = 6667
host = irc.freenode.net
password = awesomevcs 

Patch B, diff:

@@ -1,3 +1,4 @@
-port = 6667
+port = 6697
+usessl = True
host = irc.freenode.net
password = awesomevcs

You cannot just amend patch A, because the patch B depends on A:

> darcs amend                                                                                                         
patch 1925d640f1f3180cb5b9e64260c1b5f374fce4ca
Author: Daniil Frumin 
Date:   Tue Jul 21 13:23:07 MSK 2015
  * B

Shall I amend this patch? [yNjk…], or ? for more options: n

Skipping depended-upon patch:
patch 22d7c8da83141f8b1f80bdd3eff02064d4f45c6b
Author: Daniil Frumin 
Date:   Tue Jul 21 13:22:24 MSK 2015
  * A

Cancelling amend since no patch was selected.

What we will have to do is temporarily suspend patch B, amend patch A, and then unsuspend B.

> darcs rebase suspend
patch 1925d640f1f3180cb5b9e64260c1b5f374fce4ca
Author: Daniil Frumin 
Date:   Tue Jul 21 13:23:07 MSK 2015
  * B

Shall I suspend this patch? (1/2)  [ynW…], or ? for more options: y
patch 22d7c8da83141f8b1f80bdd3eff02064d4f45c6b
Author: Daniil Frumin 
Date:   Tue Jul 21 13:22:24 MSK 2015
  * A

Shall I suspend this patch? (2/2)  [ynW…], or ? for more options: d
Rebase in progress: 1 suspended patches

At this point, the state of our repository is the following: there is one (active) patch A, and one suspended patch B.

> darcs rebase changes -a
patch 4c5d45230dc146932b21964aea938e2a978523eb
Author: Daniil Frumin 
Date:   Tue Jul 21 13:28:58 MSK 2015
  * B

Rebase in progress: 1 suspended patches
> darcs changes -a
patch 21f56dfb425e4c49787bae5db4f8869e96787fb2
Author: Daniil Frumin 
Date:   Tue Jul 21 13:28:49 MSK 2015
  * A

Rebase in progress: 1 suspended patches
> cat config
port = 6667
host = irc.freenode.net
password = awesomevcs
> $EDITOR config # remove the password bit
> darcs amend
patch 22d7c8da83141f8b1f80bdd3eff02064d4f45c6b
Author: Daniil Frumin 
Date:   Tue Jul 21 13:22:24 MSK 2015
  * A

Shall I amend this patch? [yNjk…], or ? for more options: y
hunk ./config 3
-password = awesomevcs
Shall I record this change? (1/1)  [ynW…], or ? for more options: y
Do you want to record these changes? [Yglqk…], or ? for more options: y
Finished amending patch:
patch 21f56dfb425e4c49787bae5db4f8869e96787fb2
Author: Daniil Frumin 
Date:   Tue Jul 21 13:28:49 MSK 2015
  * A

Rebase in progress: 1 suspended patches

Now that we’ve removed the password from the history, we can safely unsuspend patch B (in this particular situation we actually know that applying B to the current state of the repository won’t be a problem, because B does not conflict with our modified A)

> darcs rebase unsuspend
patch 1925d640f1f3180cb5b9e64260c1b5f374fce4ca
Author: Daniil Frumin 
Date:   Tue Jul 21 13:23:07 MSK 2015
  * B

Shall I unsuspend this patch? (1/1)  [ynW…], or ? for more  options: y
Do you want to unsuspend these patches? [Yglqk…], or ? for more options: y
Rebase finished!

And that’s done!

> cat config
port = 6697
usessl = True
host = irc.freenode.net

You may use this rebase strategy for removing sensitive information from the repository, for removing that 1GB binary .iso that you added to your repository by accident, or for combining two patches into one deep down in the patchset.

Example 2: developing against a changing upstream – rebase pull

Imagine you have a fork R’ of a repository R that you are working on. You are implementing a feature that involves a couple of commits. During your work you record a commit L1 that refractors some common datum from modules A.hs and B.hs. You proceed with your work recording a patch L2. At this point you realise that after you forked R, the upstream recorded two more patches U1 and U2, messing with the common datum in A.hs. If you just pull U1 into your fork R’, you will have a conflict, that you will have to resolve by recording another patch on top.

      S
     / \
    /   \
   L1   U1

Note: if you run darcs rebase pull in R’, then the only patches that will be suspended are the ones which are already in R’. Because suspended patches gain new identity, make sure that you do not have other people’s conflicting patches present in R’.

The way to solve this would be to first do darcs rebase pull, which would suspend the conflicting patches, and then start unsuspending the patches one by one, making sure that you fix any conflicts that may arise after each unsuspend.

Consider a concrete example with two repositories rep1 and rep1_0.

rep1_0 > darcs changes 
patch ebaccd5c36667b7e3ee6a49d25ef262f0c7edf2b
Author: Daniil Frumin 
Date:   Mon Jul 27 20:56:25 MSK 2015
  * commit2

patch a7e0d92a53b0523d0224ef8ffae4362adf854485
Author: Daniil Frumin 
Date:   Mon Jul 27 20:56:25 MSK 2015
  * commit1
	rep1_0 > darcs diff —from-patch=commit2
patch ebaccd5c36667b7e3ee6a49d25ef262f0c7edf2b
Author: Daniil Frumin 
Date:   Mon Jul 27 20:56:25 MSK 2015
  * commit2
diff -rN -u old-rep1_0/dir1/file2 new-rep1_0/dir1/file2
— old-rep1_0/dir1/file2	1970-01-01 03:00:00.000000000 +0300
    +++ new-rep1_0/dir1/file2	2015-07-28 12:25:54.000000000 +0300
@@ -0,0 +1 @@
+double whatsup
	rep1_0 > cd ../rep1
rep1 > darcs changes
patch e3df0e23a3915910a81eb8181d7b3669e8f270a9
Author: Daniil Frumin 
Date:   Tue Jul 28 12:27:55 MSK 2015
  * commit2’

patch a7e0d92a53b0523d0224ef8ffae4362adf854485
Author: Daniil Frumin 
Date:   Mon Jul 27 20:56:25 MSK 2015
  * commit1
rep1 > darcs diff —from-patch=“commit2’”
patch e3df0e23a3915910a81eb8181d7b3669e8f270a9
Author: Daniil Frumin 
Date:   Tue Jul 28 12:27:55 MSK 2015
  * commit2’
diff -rN -u old-rep1/dir1/file2 new-rep1/dir1/file2
— old-rep1/dir1/file2	1970-01-01 03:00:00.000000000 +0300
+++ new-rep1/dir1/file2	2015-07-28 12:28:39.000000000 +0300
@@ -0,0 +1 @@
+touch file2
\ No newline at end of file
diff -rN -u old-rep1/file1 new-rep1/file1 — old-rep1/file1	2015-07-28 12:28:39.000000000 +0300 +++ new-rep1/file1	2015-07-28 12:28:39.000000000 +0300
@@ -1 +1 @@
-whatsup
\ No newline at end of file
+double whatsup
\ No newline at end of file

The patch commit2 from rep1_0 conflicts with commit2’ from rep1.

rep1 > darcs rebase pull ../rep1_0
patch ebaccd5c36667b7e3ee6a49d25ef262f0c7edf2b
Author: Daniil Frumin 
Date:   Mon Jul 27 20:56:25 MSK 2015
  * commit2
Shall I pull this patch? (1/1)  [ynW…], or ? for more options: y
Do you want to pull these patches? [Yglqk…], or ? for more options: y
The following local patches are in conflict:
patch e3df0e23a3915910a81eb8181d7b3669e8f270a9
Author: Daniil Frumin 
Date:   Tue Jul 28 12:27:55 MSK 2015
  * commit2’
Shall I suspend this patch? (1/1)  [ynW…], or ? for more options: y
Do you want to suspend these patches? [Yglqk…], or ? for more options: y
Finished pulling.
Rebase in progress: 1 suspended patches

Now we have one patch — commit2’ — in the suspended state. We want to resolve the conflict by amending commit2’. We will do that by unsuspending it and manually editing out the conflicting lines. This will also make it depend on commit2.

rep1 > darcs rebase unsuspend
patch e3df0e23a3915910a81eb8181d7b3669e8f270a9
Author: Daniil Frumin 
Date:   Tue Jul 28 12:27:55 MSK 2015
  * commit2’
Shall I unsuspend this patch? (1/1)  [ynW…], or ? for more options: y
Do you want to unsuspend these patches? [Yglqk…], or ? for more options: d
We have conflicts in the following files:
./dir1/file2

Rebase finished!
rep1 > cat dir1/file2
v v v v v v v

=============
double whatsup
*************
touch file2
^ ^ ^ ^ ^ ^ ^
rep1 > $EDITOR dir1/file2
rep1 > darcs amend -a
patch 40b3b4123c78dba6a6797feb619572072654a9cd
Author: Daniil Frumin 
Date:   Tue Jul 28 12:32:56 MSK 2015
  * commit2’
Shall I amend this patch? [yNjk…], or ? for more options: y
Finished amending patch:
patch c35867259f187c1bc30310f1cacb34c1bb2cce41
Author: Daniil Frumin 
Date:   Tue Jul 28 12:34:30 MSK 2015
  * commit2’
rep1 > darcs mark-conflicts
No conflicts to mark.

Another repository saved from conflicting patches, yay!


  1. See this discussion for details


Tagged: darcs, haskell, rebase

by Dan at July 28, 2015 10:15 AM

July 15, 2015

Steve Killen (nevetski)

Belonging

So, we went to the Grandfather Mountain Highland Games this past weekend. It was a thrill to be around so many characters–of similar mind and different, at the same time. The nature of a highland games is one of old flags. Scotland, in fighting for its independence from the English, had the excellent rampant lion, and of course the seven Celtic nations all had their own. The highlanders had tartans to represent their clans, all unique. (I am among them–I officially joined Clan Hamilton, being the son of Donna Hamilton, grandson of Albert Hamilton). So, naturally, the national discourse on the stars & bars continued in the camps there.

A couple things of note. Everyone had flags of all sorts strewn around, and you could see buried amongst them sometimes a Confederate rebel battle flag. My goal isn’t to talk about its history–that’s settled fact, as a racist banner adopted in promotion of the cause of continuing the practice of slavery–but about freedom of expression. We camped in Linville Falls and shuttled in, but my wife’s sister and her husband camped with some friends on the site, sharing a space with a well-known group, located off the beaten path. Hanging amidst their flags, as we strolled into the site to cook dinner, was a rebel flag, and I simply said to myself, “Are you kidding me?” They were great hosts, and the presence of a flag doesn’t give me cause to shit where I’m trying to eat. Besides, the space was somewhat separated; I could sit where I didn’t even need to look at it. I warned my friends who I brought in to join us that it was there, and no big deal was made.

By report, however, it was still an object of drama. Apparently it had initially been hung near the tent of the folks with whom my wife’s sister was staying, and they asked if it could be moved so that it didn’t seem like they were associated with it. No big deal, still; their hosts were cool with that. But the juicy bit (ah, rumor volat) is that another friend of the group came into camp and took it down of her own volition, and when confrontation ensued, she declared that they would have to choose between her friendship and the flag.

Well, I can’t make choices for other people, but that’s not the hill I would die on.

There was also a more public camp, along the main road coming into the games, and just as many other camps, it was festooned with flags. I noticed a dingy off-white towel, glaringly different from the rest of the banners, and on it had been Sharpie’d “Confederate Flag removed by request”.  On the one hand, this wasn’t a government facility; on the other, I’m not sorry at all that the organizers chose to exercise their rights as hosts to shut down a bullshit flag. And the tears of frustration at the poor folks whose free speech was being stepped on, manifest in their little protest banner–well, I couldn’t help but chuckle.

by Steve Killen at July 15, 2015 01:37 PM

July 12, 2015

Daniil Frumin (notd)

Darcs 2.10.1 (Mac OSX build)

Darcs 2.10.1 has been released!

Citing the official release notes

> The darcs team is pleased to announce the release of darcs 2.10.1 !
> ..
> 
> # What's new in 2.10.1 (since 2.10.0) #
> 
> - generalized doFastZip for darcsden support
> - support terminfo 0.4, network 2.6, zlib 0.6, quickcheck 2.8 and
> attoparsec 0.13
> - errorDoc now prints a stack trace (if profiling was enabled) (Ben Franksen)
> - beautified error messages for command line and default files (Ben Franksen)
> - fixed the following bugs:
>       - issue2449: test harness/shelly: need to handle
> mis-encoded/binary data (Ganesh Sittampalam)
>       - issue2423: diff only respecting --diff-command when a diff.exe
> is present (Alain91)
>       - issue2447: get contents of deleted file (Ben Franksen)
>       - issue2307: add information about 'darcs help manpage' and
> 'darcs help markdown' (Dan Frumin)
>       - issue2461: darcs log --repo=remoterepo creates and populates
> _darcs (Ben Franksen)
>       - issue2459: cloning remote repo fails to use packs if cache is
> on a different partition (Ben Franksen)
> 
> # Feedback #
> 
> If you have an issue with darcs 2.10.0, you can report it on
> http://bugs.darcs.net/ . You can also report bugs by email to
> bugs at darcs.net, or come to #darcs on irc.freenode.net.

I’ve updated Mac OS to version 2.10.1. You can install it with

brew install http://darcs.covariant.me/darcs.rb

Tagged: darcs, haskell, homebrew

by Dan at July 12, 2015 06:13 PM

Clinton Ebadi (clinton)

July 11, 2015

Daniil Frumin (notd)

HTTP Basic auth in Snap

Recently, I’ve implemented HTTP Basic auth for darcsden and wrote a simple wreq test for it. In this post I would like to outline the main technical details.

Server side

Transient storage

A lot of darcsden code is (especially the parts that are closer to the users’ web browser — handlers, pages, so on) is written around sessions. Sessions are stored in a special storage — implemented by the DarcsDen.Backend.Transient, but if we abstract away from the details we have a Session datatype. Authorization and authentication information is handled by sessions using functions setUser :: (BTIO bt) => Maybe User -> Session -> Snap Session, notice :: (BTIO bt) => String -> Session -> Snap () (display a message to the user) and others. The BTIO bt part is just a synonym for

type BTIO bt = (BackendTransient bt, ?backendTransient :: bt, MonadIO (BackendTransientM bt))

Which basically says that we are operating with a transient backend that supports all of necessary operations, and we can also do IO in it. Right now there are only two transient backends (read: two ways of storing sessions): Redis and in-process memory.

Running sessions

If we have a piece of Snap code that we want to “sessionify” we use the following interface:

withSession :: (BTIO bt) => (Session -> Snap ()) -> Snap ()

What this does is it basically checks for a cookie — in case it is present it grabs the session information from the storage (in accordance with the cookie); if the cookie is not present it creates a new session and stores it in a cookie.

If we have a page of a type Session -> Snap (), we might want to give user an option to do HTTP authentication on that page. We introduce another function

withBasicAuth :: (BP bp, BTIO bt) 
              => (Session -> Snap ()) 
              -> (Session -> Snap ())
withBasicAuth act s = do
    rq  do
          rawHeader <- maybe throwChallenge return $ getHeader “Authorization” rq
          let (Just (usr,pw)) = getCredentials rawHeader
          c  errorPage “Unknown user”
            Just u -> if checkPassword (fromBS pw) u
                         then doLogin (fromBS usr)
                         else errorPage “Bad password”
      _ -> act s

So, what is going on in here? First of all, we check if the “login” parameter is set to “true”. If it does, we try to get the “Authorization” header, de-encode it, and check whether the credentials are good.

throwChallenge :: Snap a
throwChallenge = do
    modifyResponse $ (setResponseStatus 401 “Unauthorized”) .
                     (setHeader “WWW-Authenticate” “Basic realm=darcsdenrealm”)
    getResponse >>= finishWith

If the response header is present, it is of a form Basic x, where x is a base64 encoded string user:password. We can extract the credentials from the header like this:

import qualified Data.ByteString          as B
import qualified Data.ByteString.Base64   as B
…
getCredentials :: B.ByteString  — ^ Header
               -> Maybe (B.ByteString, B.ByteString) — ^ Possibly (username, password)
getCredentials header =
    if (isInfixOf “Basic “ header)
      then fmap extract (hush (B.decode (B.drop 6 header)))
      else Nothing
  where
    extract cred = case (B.breakByte (c2w ‘:’) cred) of
                     (usr, pw) -> (usr, safeTail pw)

On the client

The tests that I am currently writing for darcsden are all of the same form: I use wreq to do requests to the darcsden server, then, if necessary, I run taggy to extract information from the webpage, and compare it to the “canonical” information.

As it turns out, doing HTTP Basic Auth is very easy with wreq! First of all, we define a function for doing a GET request that will do some exception handling for us:

getSafeOpts :: Options -> String -> IO (Either Status (Response ByteString))
getSafeOpts opts url = fmap Right (getWith opts url) `catch` hndlr
  where
    hndlr (StatusCodeException s _ _) = return (Left s)
    hndlr e = throwIO e

This way, we won’t get a runtime exception when accessing a non-existing page or getting a server error. Doing a GET request with HTTP Basic Auth is now very easy:

getWithAuth :: (String, String) -> String -> IO (Either Status (Response ByteString))
getWithAuth (username,pw) url = getSafeOpts opts url
  where
    opts = defaults & auth ?~ basicAuth (toBS username) (toBS pw)
                    & param “login” .~ [“true”]

In that snippet we use lenses to set up an auth header and an HTTP parameter (?login=true).

Finally, after obtaining a Response ByteString, we can parse it with taggy-lens:

parsed :: Fold (Response L.ByteString) Text.Taggy.Node
parsed = responseBody 
       . to (decodeUtf8With lenientDecode)
       . html

We can then play with it in GHCi

*Main> Right r  r ^.. parsed
[NodeElement (Element {eltName = “DOCTYPE”, eltAttrs = fromList [(“html”,””)], eltChildren = [NodeElement (Element {eltName = “html”, eltAttrs = fromList [], eltChildren = [NodeElement (Element {eltName = “head”, eltAttrs = fromList [], eltChildren = [NodeElement (Element {eltName = “title”, eltAttrs = fromList [], eltChildren = [NodeContent “localhost”]}),NodeElement (Element {eltName = “link”, eltAttrs = fromList [(“href”,”http://localhost:8900/public/images/favicon.ico”),…

If we want to check that we are indeed logged in correctly, we should look for the “log out” button. Taggy does all the heavy lifting for us, we just have to write down a lens (more precisely, a fold) to “extract” a logout button from the page

logoutButton :: HasElement e => Fold e Text
logoutButton = allAttributed (ix “class” . only “logout”)
             . allNamed (only “a”)
             . contents

logoutButton searches for <div class=“logout”> and returns the text in the link inside the div. There might be many such links inside the node, hence we use a fold.

*Main> r ^.. parsed . logoutButton
[“log out”]

In this case, since we only care if such link is present, we can use a preview

*Main> r ^? parsed . logoutButton
Just “log out”

Conclusion

Well, that’s about it for now. I regret taking way too much time writing this update, and I hope to deliver another one soon. Meanwhile, some information regarding the darcsden SoC project can be found on the wiki.


Tagged: darcs, haskell

by Dan at July 11, 2015 09:27 AM

July 08, 2015

Clinton Ebadi (clinton)

July 05, 2015

Steve Killen (nevetski)

Doing the readings

Two major things on the horizon: producing a caring for a wee, infant boy, and moving to Mexico. “What?” you just said. “You’re moving to Mexico?!” Yeah, no big deal, we’re just going to go teach English abroad while raising our little bairn. :)

Lots of reading in the pipeline. First up is Dr. Karp’s The Happiest Baby On The Block, a research-based discussion of calming techniques founded on the theory that newborns need an extra trimester, and our job is to provide it by swaddling, swinging, and shushing them just like they had during the first 9 months of growth. It’s pretty fantastic so far, and I feel like I’m going to have a lot of fun being a dad. Key sentence today: “The fastest way to succeed in stopping your baby’s cycle of crying is to meet his level of intensity” (Emphasis Karp). I. Am. So. Stoked.

Next in the queue is the Moon guide, Living Abroad in Mexico. I’m still waiting for it to arrive, but it looks to be full of usefulness. I have many questions about the process, and it looks like it’s got a lot of answers! We’re looking at Merida, on the Yucatan. If you have any supportive advice, feel free to chime in!

Time, it marches on…

by Steve Killen at July 05, 2015 07:39 PM

July 01, 2015

Steve Killen (nevetski)

Day 1

Today marks a new practice: no imgur for 3 weeks. It’s a fantastic place for anthropological investigation and ruminating around the landscape of ideas and images with other nerds, but I want to shift my mental habits to more immediate, less abstract domains. I have very practical goals now, and I need to stop just wrestling with ideas themselves. This state of mind was why I went for, and acquired, my degree in philosophy–it’s what I do, regardless of anything else. But as amazing a tool for rational inquiry and exploration of the boundaries of human expression in 140 characters as imgur is, it’s got to make room.

I’m not quitting forever, just 21 days. So, here’s to day 1.

(I have abandoned HabitRPG. I don’t know if I’ll come back to it yet. But I got by without it before, and I’m going to do it again.)

by Steve Killen at July 01, 2015 12:14 PM

June 30, 2015

Steve Killen (nevetski)

Changes of tension and flexion

I wanted to start this off as a letter. “Greetings,” I was all set to begin. Time was people read this, but then I let it languish, as I do now and again. So I guess I don’t really have an audience to greet. But I’m picking it up again, so you lucky readers buckle in. :) So much change has gone on in my life these last six months. Some of it I willed to being, but some of it I allowed to happen through inertia (or lack thereof).

As of June 19th, I am a married man. It’s the internet, so if you know me, you know my wife.  She’s amazing, beautiful, kind, generous, thoughtful, incredibly intelligent, compassionate, whole-hearted, nerdy… I have too many adjectives jammed at the space where the words come out to really do her justice. As we courted over the last summer and into the winter, I awakened to the very real changes that I had been wanting to make in my life, changes that she not only supported but encouraged. And I found myself not only supporting her goals and motivations, but supporting just the beauty of her existence, and all those underlying motivations and goals yet to emerge in her consciousness. As I told my parents practically the moment we began dating: she’s the one. And as we dance this dance through life, I am awed by the profundity of joy that is this life with her.

I have also completed my teaching in NC. I finished up the third year here, and I have learned a great deal about education; as the new teacher steps into my place, I am confident I have brought an academic rigor to the Latin program at Middle Creek that had been lacking before I arrived. We are looking elsewhere for jobs, as this state is clearly not interested in retaining its teachers.

And in the glorious narrative tradition of the three-topic discussion, I am about to become a father. We are expecting our son to arrive into the world around September 21st, and he’s got all ten fingers and toes, so I’m pleased as punch :)

As one chapter of my life closes and another opens, I am thrilled to renew my commitment to writing. I feel like my creativity had been drained from me these last few years, and it is time to touch base with the eternally-flowing font inside me. Maroon’s stories call out to be told, and life doesn’t stop for the living.

by Steve Killen at June 30, 2015 10:08 PM

June 22, 2015

Daniil Frumin (notd)

Darcs binaries for OSX with Homebrew

Recently I’ve updated my Darcs homebrew build to Darcs 2.10. You can install it with

brew install http://darcs.covariant.me/darcs.rb

The formula contains a context (--exact-version) and it is a static binary.


Tagged: darcs, haskell, homebrew

by Dan at June 22, 2015 12:33 PM

June 11, 2015

Clinton Ebadi (clinton)

June 01, 2015

Sajith Sasidharan (sajith)

hostapd

Recently I learned that my netbook (a 2012 Acer Asprire One) could be configured as a home WiFi access point, with very little effort.

This trusty little computer with a really awful keyboard saw me through the hard times when my untrustworthy Thinkpad broke down. These days it is hooked to the ISP's router via ethernet, and is always on, functioning as a mediatomb and owncloud and what not server. It runs Debian stable.

The ISP's router plays rather quite poorly with Windows computers and Windows phones – which is really surprising. Running hostapd in the netbook and using that as the access point solved that problem nicely.

I needed some tiny changes in /etc/network/interfaces for a bridge interface setup:

auto lo br0
iface lo inet loopback

allow-hotplug eth0

# Bridge setup
iface br0 inet dhcp
        bridge_ports eth0 wlan0

This is what /etc/hostapd/hostapd.conf looks like:

interface=wlan0
driver=nl80211
bridge=br0

logger_syslog_level=3

country_code=US
ieee80211d=1

ctrl_interface=/var/run/hostapd
ctrl_interface_group=0

ssid=<whatever>

hw_mode=g

channel=1

wme_enabled=0
macaddr_acl=0
auth_algs=1

wpa=2
wpa_passphrase=<whatever>
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

A few things of note:

  • If you want to try this out, you might want to run "/sbin/iw list" and make sure that AP is listed under "Supported interface modes". Mine has these lines:
[...]
Supported interface modes:
         * IBSS
         * managed
         * AP
         * AP/VLAN
         * monitor
[...]
  • To verify that hostapd configuration is error-free, this command was useful: /usr/sbin/hostapd -d /etc/hostapd/hostapd.conf
  • The Android app Wifi Analyzer helped in scanning the WiFi "neighborhood" and picking up an interference-free channel.
  • Arch wiki has a lot of details.

June 01, 2015 05:00 AM

May 22, 2015

Sajith Sasidharan (sajith)

Holland, Michigan

Over the weekend, we visited Holland, Michigan, a week after their Tulip Time Festival, and gawked at some of their remaining tulips.

Holland is a rather nice town with the appropriate tourist traps for a place of its repute. The drive there through countryside was more interesting though: Michigan countryside reminded us of Maine countryside, but with better roads and without the seaside and crustaceans. (It also seemed that Michigan roads are so much better built and maintained than Indiana roads, in spite of lower gas prices in Michigan. What's up with that.)

2015-05-16-09-29-36-holland.jpg

Figure 1: Veldheer Tulip Gardens.

2015-05-16-09-36-22-holland.jpg

Figure 2: Veldheer Tulip Gardens.

2015-05-16-09-41-58-holland.jpg

Figure 3: Veldheer Tulip Gardens.

2015-05-16-09-19-07-holland.jpg

Figure 4: Veldheer Tulip Gardens.

2015-05-16-09-21-43-holland.jpg

Figure 5: Veldheer Tulip Gardens.

2015-05-16-09-27-45-holland.jpg

Figure 6: Veldheer Tulip Gardens.

2015-05-16-09-28-48-holland.jpg

Figure 7: Veldheer Tulip Gardens.

2015-05-16-09-35-54-holland.jpg

Figure 8: Veldheer Tulip Gardens.

2015-05-16-09-32-46-holland.jpg

Figure 9: Veldheer Tulip Gardens.

2015-05-16-09-37-50-holland.jpg

Figure 10: Veldheer Tulip Gardens.

2015-05-16-10-31-51-holland.jpg

Figure 11: Lake Michigan.

2015-05-16-10-42-51-holland.jpg

Figure 12: Lake Michigan.

2015-05-16-11-36-23-holland.jpg

Figure 13: At Windmill Island.

2015-05-16-15-10-49-holland.jpg

Figure 14: Downtown Holland.

2015-05-16-15-12-49-holland.jpg

Figure 15: Downtown Holland.

Holland has a still-operational windmill (named "De Zwaan"), which was transplanted from the Netherlands in the sixties. Because I'm dumb with cameras, I did not have a plan B for when the SD card errored out; nor did I have the right lens on the camera. Thus it happens that I don't have a good picture of De Zwaan, which is not really a big deal in The Grand Scheme of Things.

On the way home, we stopped at a friendly farmer's house to buy some eggs. They had ten cats living around the house. I think this is The Single Most Important Lesson I learned from this trip: if one moves to the countryside, one can have ten or more cats around the house if one so wishes! (And chicken! And geese! And dogs! And goats! And cows! And horses! And that would be really cool.)

Someday I will turn into Old Farmer MacDonald, and my friends, you will not recognize me when that happens.

May 22, 2015 05:00 AM

May 13, 2015

Daniil Frumin (notd)

Hoogle inside the sandbox

Introduction

This is my first post from the (hopefuly fruitful!) series of blog posts as part of my Haskell SoC project. I will spend a great chunk of my summer hacking away on DarcsDen; in addition, I will document my hardships and successes here. You can follow my progress on my DarcsHub.

This particular post will be about my working environment.

The problem

Hoogle is an amazing tool that usually needs no introduction. Understandably, the online version at haskell.org indexes only so many packages. This means that if I want to use hoogle to search for functions and values in packages like darcs and darcsden, I will have to set up a local copy.

Cabal sandboxing is a relatively recent feature of the Cabal package manager, but I don’t think it is reasonable in this day to install from the source (let alone develop) a Haskell package without using sandboxing.

The problem seems to be that the mentioned tools do not play well together out of the box, and some amount of magic is required. In this note I sketch the solution, on which I’ve eventually arrived after a couple of tries.

Using hoogle inside a Cabal sandbox

The presumed setup: a user is working on a package X using the cabal sandboxes. The source code is located in the directory X and the path to the cabal sandbox is X/.cabal-sandbox.

Step 1: Install hoogle inside the sandbox. This is simply a matter of running cabal install hoogle inside X. If you want to have a standard database alongside the database for your packages in development, now is the time to do .cabal-sandbox/bin/hoogle data.

Step 2: Generate haddocks for the packages Y,Z you want to use with hoogle. In my case, I wanted to generate haddocks for darcs and darcsden. This is just a matter of running cabal haddock --hoogle in the correct directory.

Step 3: Convert haddocks to .hoo files. Run the following commands in X/:

.cabal-sandbox/bin/hoogle convert /path/to/packageY/dist/doc/html/*/*.txt

You should see something like

Converting /path/to/packageY/dist/doc/html/Y/Y.txt
Converting Y... done

after which the file Y.hoo appears in /path/to/packageY/dist/doc/html/Y/

Step 4: Moving and combining databases. The hoogle database should be stored in .cabal-sandbox/share/*/hoogle-*/databases. Create such directory, if it’s not present already. Then copy the ‘default’ database to that folder:

cp .cabal-sandbox/hoogle/databases/default.hoo .cabal-sandbox/share/*/hoogle-*/databases

Finally, you can combine your Y.hoo with the default database.

.cabal-sandbox/bin/hoogle combine /path/to/packageY/dist/doc/html/*/*.hoo .cabal-sandbox/share/*/hoogle-*/databases/default.hoo
mv default.hoo .cabal-sandbox/share/*/hoogle-*/databases/default.hoo

And you are done! You can test your installation

$ .cabal-sandbox/bin/hoogle rOwner
DarcsDen.State.Repo rOwner :: Simple Lens (Repository bp) String

For additional usability, consider adding .cabal-sandbox/bin to your $PATH.


Tagged: cabal, darcs, haskell, hoogle

by Dan at May 13, 2015 09:54 PM

April 22, 2015

Sajith Sasidharan (sajith)

OpenPGP Key Transition

I'm a terrible person: I kept my 2007-vintage 1024D OpenPGP keypair around for the longest time, even though I should have discarded it several years ago.

To give you an idea about the depths of slothfulness and procrastination I have fallen into: all Debian developers phased out their 1024-bit DSA keys around 2009 or so. I found it fit to transition to a new key a good six years later. Shame on me!

In my defense, I rarely ever send or receive encrypted email. (Not entirely true: I received a deluge of encrypted, signed, and encrypted and signed email – both OpenPGP and S/MIME – from my students, when I was TA-ing a security class, but back then I was a stressed out graduate student, and I indeed didn't see the occasion fit to upgrade my GPG/PGP keypair.)

In my further defense, using PGP is not the most intuitive task one might perform with a computer: as some people argue, it might be even time for PGP to die. It still is one of our best defenses against several hostile actors today, so until something better comes along, using PGP is a good idea.

Ideally the lack of email encryption should change: not only to protect privacy, confidentiality, and integrity of our email messages, but also as a means of protest against mass surveillance, both by various private entities and by governments; and to support principled free software developers like Werner Konch, who keep pressing on.

Anyway, my story is that I'm transitioning to a RSA 4096-bit PGP key. Tradition mandates that one must publish a transition statement on an occasion like this. My transition statement is available here, and it is signed with both my old and new keys to validate the transition:

https://nonzen.in/files/key-transition-2015-04-23-sajith.txt

(The statement was updated to use long 16-character key IDs.)

You can download the statement and gpg --verify it against the old and new keys, given below. I have also posted the new public key, as well as the old one, for good measure.

The old key (id 0xB4D228AD9DB8FF06) is now set to expire in an year:

pub   1024D/0xB4D228AD9DB8FF06 2007-09-02 [expires: 2016-04-21]
      Key fingerprint = CB80 0BA6 7D13 B10A 6FBB  D43E B4D2 28AD 9DB8 FF06

And the new key is:

pub   4096R/0x0C6DA6A29D5F02BA 2015-04-22 [expires: 2020-04-20]
      Key fingerprint = 22D9 BFBA 256B 7BFA 7B16  187C 0C6D A6A2 9D5F 02BA

The new key, signed with the old key, should be present in keys.gnupg.net and should eventually propagate to other keyservers as well. If you have signed my old key in the past, please consider signing my new key as well, after the necessary verification steps. (Thank you!)

Notes

Because I will forget what I have done any moment from now, I thought it would be a good idea to write down what I have done:

1. Update ~/.gnupg/gpg.conf

Added these lines to the bottom of ~/.gnupg/gpg.conf:

personal-digest-preferences SHA512
cert-digest-algo SHA512
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed

keyid-format 0xlong
with-fingerprint

2. Create new key

gpg --gen-key

Be sure to pick a 4096-bit RSA key. Some folks have been using 8192-bit keys as back as 2009 by patching GPG sources. Somewhat surprisingly 8192-bit keys aren't available in GPG official releases even today! Since I have no inclination to mess with sources, I chose a 4096-bit RSA key.

3. Add other UIDs

Here's where you add your all other email addresses.

gpg --edit-key [new key id]
...
command> adduid
...
command> save

4. Set primary UID

We need to designate one of the UIDs as the primary one.

gpg --edit-key [new key id]
...
command> uid 1
...
command> primary
...
command> save

5. Generate a revocation certificate

This is for future use. The revocation certificate must be stored away somewhere safe.

gpg --gen-revoke [new key id] > [new key id]-revoke.asc

6. Sign new key with old key

Assure the world that both belong to the same person.

gpg --default-key [old key id] --sign-key [new key id]

7. Publish the new key

Send the new key to a friendly neighborhood public key server.

gpg --keyserver keys.gnupg.net --send-key 9D5F02BA

8. Write a transition statement

Write the traditional transition statement, and sign it with the old and new keys:

gpg -a -u [old key id] -u [new key id] --clearsign statement.txt

9. Holler from the rooftops

In addition to the public keys, publish the transition statement, write a blog post, tweet about it, and publish the new key in keybase.io, like all the cool kids do these days.

10. Profit?

Hardly. This ain't no such business.

April 22, 2015 05:00 AM

April 02, 2015

Sajith Sasidharan (sajith)

Artisanal Defrosted httpd Backdoor

Back when I worked as a teaching assistant for a network system security class, I handled the labs, and one of the labs was on malware, so I assigned my students with this task: find pieces of malware that were surreptitiously installed into their (individual) virtual machines, and scrub the the VM clean of all such nasty bytes.

I installed a basic root shell (that bound to an innocent-looking port, with an innocent-looking process name), and an Apache web server module called mod_rootme. When Apache web server has mod_rootme enabled, if you connect to the web server port and issue the magic incantation ('get root'), you will get a root shell. Boom.

The mod_rootme code is fairly old – it was written by Christophe Devine in 2004. It seems that Christophe doesn't maintain this code anymore. I could not find working versions of mod_rootme anywhere: the latest I found was version 0.4 of mod_rootme in a blog post from 2009. (That is a wayback machine link. The original site seems to have vanished from the Internet.)

Since mod_rootme 0.4 did not compile out-of-the-box, I made some changes to make it work: mainly to build it with apxs, the APache eXtenSion tool. I also removed some old code I didn't mean to use, mainly the code that supported older versions of Apache web server. Other than having to figure out apxs-based build system and a tiny bit of refactoring, I haven't sweated this much. So: apply caveat emptor and all that really hard.

Christophe is known to be a platform-neutral programmer – the original Makefile has rules for building mod_rootme on Linux, FreeBSD, OpenBSD, MacOS X, Cygwin, SunOS, IRIX, HPUX, OSF; and against Apache versions 1.x, 2.x, and 2.2. I have tested this code only on Debian 8.0 (and previously on Ubuntu Server 12.04 for the class, but not this time), and it seems to work the way it should.

Now, about the assignment: I imagined the first root shell would be to easy to detect, but no one in the class found it. I did not expect all students to find mod_rootme (it doesn't actively maintain any open ports or spawn a suspicious-looking process, after all), but everyone did! That was actually pretty trivial, since malware detection programs such as rkhunter and unhide can detect the presence of mod_rootme.

For this very reason, I am hoping that it should not be too harmful to have this code in circulation again, and that someone somewhere will find the code instructional.

I have posted my modifications to mod_rootme in github.

April 02, 2015 05:00 AM

March 31, 2015

Steve Killen (nevetski)

Well, there went March

It has been a wild month. Much positive change, but also some waning in my habits. And I’m still putting off the monster.

I love climbing mountains, at least. And falling down them.

I’ve been so distracted; so many things are floating around me that are Stuff I Must Do Or Else. It’s to the point where Or Else has become a meaningless concept to me. (Of course, that doesn’t remove it of its teeth; I have just stopped caring.) But, at least, I have been showing up every single day, fighting the big fires, and then tending to the little ones if there’s time. The biggest thing I am seeing is the need to stop numbing out with facebook and imgur. The discourse is a pretty intense reward, but it sucks me in and becomes more habitual, and then it just is the thing I do, instead of being present in the real world. And the Or Else marches closer.

So many things I want to write about, but my time grows short. So, another post.

by Steve Killen at March 31, 2015 08:28 PM

March 08, 2015

Steve Killen (nevetski)

HabitRPG progress report

My tumble continued unabated as February drew to a close. But I’m getting back on top in terms of staying productive.

My costume is awesome.

Still procrastinating, but I am also doing more. The no-armor rule has fueled a great deal of that; I must be productive or die more. I slipped up once, but I’m finally back to a point where I can heal myself again with magic. It doesn’t do much (15 mana for 2.2 HP), but it cuts down on healing potions a skosh. And the more things I do on my to-do list, the more magic I get back.

There are some new dimensions that are being added to my life–stay tuned for some fairly exciting news.

by Steve Killen at March 08, 2015 03:56 PM

Classroom struggles

One of the most difficult-seeming tasks for a teacher is to inspire your students to study the material you’re teaching outside of class. The results of my first unit’s test–delayed because of 2 weeks worth of snow days–reinforces that, because the results are so frustratingly low. I’m not a teacher inclined to curve tests numerically, as we have the option of a retake and also a remediation activity that adds a small percentage to the grade. But it tells me a number of things, both about my test, my expectations for the students, and their level of preparation for the material. But I can only place a part of it on the students. So, back to the drawing board I go, to think of ways to reinforce their existing knowledge and help build up the concepts they’re clearly struggling with. This next unit will give me a little time, as we’re shifting from the passive voice (a big step) to looking at how adjectives form in comparative and superlative degrees (more of a lateral move). The first thing we will be learning is the perfect passive participle, which will be at least somewhat familiar territory for them, and it will allow me to re-address relative clauses and passive voice.

I am trying an experiment, too, with homework. It didn’t go as well as I had hoped, partly because of the snow days hitting right when it was ramping up into gear. It’s a homework sheet, that allows students to choose their paths rather than have me micro-manage it for them, incorporating routine practice and independent cultural exploration. One of its primary objectives is to foster a sense of self-driven inquiry. But I am groaning under the burden of it–my initial formulation was too confusing, and I didn’t deploy it in stages, so I have 3 blocks of material to grade, half of which is either incomplete or lacking in understanding how the assignment is structured. But it is not a complete bust! I have something I can now improve, and the students are still practicing. However: they did not over the snow days, by their own report, despite my attempts to communicate with them over Blackboard their assignments. That’s the most frustrating part. I have reiterated throughout the first six weeks that studying every night was critical, but that expectation was simply ignored when push came to shove.

Lesson learned: be more proactive. I did, indeed, drop the ball to some extent. This semester is eating me alive because of the various priorities I have that are completely not school-related. (More on that soon…) Now, I must dig out of my hole and get on top of the dirt pile again. I had such a great start to the spring semester, but it got away from me. Time to get it back.

by Steve Killen at March 08, 2015 03:38 PM

February 24, 2015

Steve Killen (nevetski)

A model of hesitation

So I headed out to work today, thinking we’d probably be getting early release (most forecasts called for afternoon snow). About two-thirds of the way through my 45-minute commute, i.e., 6am–yes, I leave typically around 5:30am–it began snowing. I checked the county Web site when I got to the parking lot, and my suspicions were correct: lo, we were set for delayed opening. A few other early-arriving teachers were dumbfounded as I shared the news with them; they too had been snared by the vagaries of travel time and school hours. I caught up with a few beloved colleagues also making their way in, and as the big, fat flakes drifted noiselessly and unrelentingly down to the whitening tarmac, which had done its best to retain heat but eventually gave up under last night’s brutal chill and the morning’s crystalline onslaught, it was patently obvious that the delay was only to buy the county some time before the inevitable decision.

Making the trudge to my remote trailer up the hill and out by the tennis courts, truly a world apart from the main building, I had only just settled in to my classroom to get some preparatory work done when an announcement rang out over the intercom from our principal: there would be another announcement very soon about whether school would remain open or close. And only moments after that, the same crackling voice boomed out with the decision we all knew: classes had been cancelled. Anti-climactic in the highest order, and a little frustrating–it felt a little like a marked lack of sensitivity for the distances educators and students travel. But, business as usual where I teach.

The tennis court parking lot at 9am

In a completely unexpected development, however, another voice gently informed us hapless souls who had had to commit to our morning journeys of some succor. In the cafeteria, there was a pile of fresh, hot sausage biscuits, free to those who wanted ‘em, first come first serve. Needless to say I engaged in some light calisthenics down (already!) snow-covered stairs and lawn to get there before they all disappeared. The crowd was in a mostly jovial mood–yes, even hot-footing it did not get me there first–and we snacked and joked and shared some rare communal time, not beset by such time sinks as professional development (as useful as it can sometimes be) or staff duties involving the monitoring of students (as amusing as it can often be). But as we dispersed, I felt a grim undertone in the air. We had to consider our journeys home again. I thought about it, discussed with a few others, and then decided to take advantage of the time and wait for the morning traffic to subside. I was raised in the north, and therefore inculcated with at least a modicum of snow traffic culture and experience. And I wanted no part of driving next to people who didn’t understand that in snow, if you use the brake more than gently, you’re asking for trouble.

So, merrily I worked along, updating my students about the day’s expectations and tying loose ends. It went by faster than it ever had before (because, naturally, I was actually accomplishing things), and I kept telling myself I would leave in just a few more minutes. When the clock showed 11, though, I put as much as I could on Google Drive and hastened to depart. There must be some sort of social dynamic akin to physics’ inverse square law that describes how much time a teacher has and how much work he or she thinks she can do. The less time I have, the more I think, “oh, but just one more thing!” At 11:45, after ascertaining a route that did not have any reported accidents (there were 3), I actually departed.

Farrington Road north of the lake

I chose well, avoiding the local main road (NC 55, with its dozens of stoplights) and taking the back way through Apex to NC-64. I had only one scare at the 64 interchange, when just a little too much brake gave me an opportunity to examine first-hand how the Honda Fit handles snow and ice. Spoiler: not well. But, I knew how to handle the car, and I skidded into a graceful turn that looked like I meant to do that. Yeah. The actual source of danger was Farrington Road, which cuts across Jordan Lake–the northerly part of it is fairly woodsy, and the road was still properly coated with snow. I saw not one but two be-ditched vehicles while I trundled along at 20mph, one of which had acquired the assistance of a Jeep with a winch to help drag it out. That Jeep was skating all over the road just trying to pull its brother pickup out. (The other vehicle, a van, was completely overturned, though it looked as though the driver had been able to climb out safely. Nobody was on the scene, so I can only hope.)

I struggle to imagine the series of decisions that resulted in this.

But the best part about the drive was my discovery of the Fit’s supremely useful gear paddles! When I bought the Fit, I had fleetingly considered them but hadn’t really had occasion to employ them; while I know how to gear-brake, the last time I had actually had to practice it was 3 summers ago descending the Continental Divide. My experience on NC-64 reminded me to use them instead of braking, and it was a sublime experience to tap a button on the steering column and have it downshift without batting an eye. The gear control of a manual, with all the convenience of an automatic. The gear-braking saved me from several otherwise potentially hairy incidents, and while it took me an extra half-hour to arrive home, I had only pleasant memories of snowy woods and frigid lakes, the snow falling all around in a graceful play of light and silence.

But did we really need to wait until this morning to make the call? Well, I guess everything is as it should be.

by Steve Killen at February 24, 2015 09:31 PM

February 17, 2015

Steve Killen (nevetski)

February has been rough

But it’s not over yet, and I feel like I can get it back. To start, here’s my HabitRPG for February so far:

A Healer, supposedly

So, I made it to level 10 and became a Healer by the end of January. I was rocking out, learning how to use “poison” Dailies to good effect. But when the school semester began in earnest, I started to lose my grip on the really important tasks. Plus side to it, I’m actually getting consequences, rather than just feeling guilty; half my gear has been destroyed and I’ve lost so much coin. I’m at the point of losing something really valuable to me, my Gumdrop Sword. (Oh noes!) I can’t just re-buy it, and it’s just cool-looking. So I just need to suck it up, McNugget, and do the stupid poison dailies that have been plaguing me.

One useful side-effect about this is that it’s also a calibration of my self-honesty. In January I was getting a handle on how to use it, and I had only been plugging in things that were vaguely important (I mean, sure, ideals, but not a lot of practical substance). And it was good practice. But now I’ve pared down, relegating the idealistic stuff to Habits and using the Dailies for the truly consequential items. It is showing me how badly I do procrastinate on things that seem patently easy to do, and the more important it is, the more likely it seems I’ll quail at the task. Shame rears its ugly head and nibbles at my soul.

So, going forward, I’m going to stop wearing armor. I’ll buy stuff to wear for costumes, but boosting my CON is just protecting me from the harsh reality of bad habits. (I will, however, accept other stat boosts, because they increase my rewards for doing good things. It is, if you will, a double-edged sword.)

I introduced this to one of my ADD kids, and he really took to it. To his credit, he immediately saw the importance of honesty that this system requires, and that it actually nourishes. I feel like I’m actually doing some good in the world these days.

Back to the grind!

by Steve Killen at February 17, 2015 05:51 PM

January 24, 2015

Sajith Sasidharan (sajith)

NOLA and back

2014-12-27-22-02-30-nola.jpg

Figure 1: Summarizing New Orleans in one sign board.

We visited New Orleans, Louisiana in December, around Christmas time. New Orleans, that southern town known for its music, cuisine, writers, drunken reveries, Mardi Gras, Jazz and Blues music, Mississippi river, swamps, and corrupt public servants. That this town chose to name their airport after a musician tells us a thing or two about them, doesn't it?

• • •

2014-12-25-15-31-17-farm.jpg

Figure 2: Somewhere in Kentucky.

2014-12-25-16-11-58-lbtl.jpg

Figure 3: Land Between the Lakes, Kentucky.

2014-12-25-17-24-06-farm.jpg

Figure 4: Barn, Tennessee.

We drove from Indiana to Lousiana through Kentucky, Tennessee, and Mississippi. We mainly took country roads, avoiding the interstate highways because we felt that it is the right way to see the country, and because we felt some love and allegiance to John Steinbeck who wrote, in Travels with Charlie, that:

These great roads are wonderful for moving goods but not for inspection of a countryside. You are bound to the wheel and your eyes to the car ahead and to the rear-view mirror for the card behind and the side mirror for the car or truck about to pass, and at the same time you must read all the signs for fear you may miss some instructions or orders. No roadside stands selling squash juice, no antique stores, no farm products or factory outlets. When we get these thruways across the whole country, as we will and must, it will be possible to drive from New York to California without seeing a single thing.

It is indeed is possible to drive across United States without really seeing much. We felt a compulsion to see the country, as much as one can see it by driving our tiny hatchback through the backroads. I would like to report that we were rather successful in that, and that we would like to do this more often. Highways are odd – they remain simultaneously boring and scary.

• • •

We ate our rather unmemorable Christmas dinner (pizza) at a gas station. (Note to self: don't ever do this again. You will feel sorry for the gas station employees, who really should spend the evening with their families, even if your snobby pagan self don't care that much about Christmas festivities.)

We spent the night in a place called Southwood Inn in Selmor, Tennessee. The inn's front desk had copies of The McNairy County News, which, on its front page, reported the story of an rescued dog, whom his rescuers called "Chip". The newspaper said:

The vet said Chip had intention on his head and had suffered blunt force trauma where someone had apparently hit him on the head in an effort to kill him. Several of his teeth had been knocked out.

There is swelling and hair loss around his face and both his eyelids are missing from what the vet thinks is from someone pouring flammable liquids on him and setting him on fire. The tip of his penis was cut off and he is unable to control his urination. Surgery to fix Chip is estimated to cost over $2,000.

2014-12-25-22-53-22-chip-1.jpg

Figure 5: Chip dog's tragic story.

2014-12-25-22-54-33-chip-2.jpg

Figure 6: "… his penis was cut off and he is unable to control his urination."

On one hand, I am glad that Chip is finally in good hands, and that a paper like The McNairy County News exists, and they are willing to give space in front page to a story like this. On the other hand, there exists humans that bring shame to our species…

• • •

2014-12-26-11-37-20-natchez_trace.jpg

Figure 7: Natchez Trace Parkway, Mississippi.

2014-12-26-12-49-57-natchez_trace.jpg

Figure 8: French Camp Academy on Natchez Trace, Mississippi.

2014-12-26-15-30-46-ms-cows.jpg

Figure 9: Cow herd excited to meet a human, Mississippi.

In Mississippi, we came across The Natchez Trace Parkway, the longest stretch of road we drove on, the least inhabited stretch of land we saw on our way, and perhaps the prettiest.

The Natchez Trace is an old path that that connected Natchez, Mississippi to Nashville, Tennessee. Native American tribes used it for centuries, and then early European explorers followed. When steamboats appeared in Mississippi River, the Trace lost its prominence. These days the Natchez Trace Parkway, maintained by National Park Services, preserves the Old Natchez Trace's memories.

• • •

2014-12-27-15-58-43-nola.jpg

Figure 10: Brass Band at the French Quarter.

2014-12-27-21-32-49-nola.jpg

Figure 11: At Blue Nile Bar.

2014-12-27-20-22-53-nola.jpg

Figure 12: Washboard Chaz Trio playing at Blue Nile Bar.

2014-12-27-22-07-25-nola.jpg

Figure 13: Seen on Frenchmen street.

We did the touristy things (taking the streetcar on Canal Street, checking out the Audubon Butterfly Garden and Insectarium, dragging our feet through French quarter, gawking at street life, sipping hand grenade while out in the street – those kind of things). We also did get to hang out with a bunch of drunk itinerant musicians, who proudly called themselves "homeless bums".

2014-12-27-22-22-29-mark_achu_nick.jpg

Figure 14: Itinerant people.

Bob, Nick, and Mark are from Michigan, and were planning to head to Florida (for the winter months, I believe) from New Orleans. They stopped us on the street to sell us jokes: a joke for a dollar, that was the offer. We did not have any money on us, but they told us some jokes anyway. I don't remember the jokes anymore, but I do remember laughing much, and I do have a recording of the song they sang for us.

• • •

2014-12-28-13-43-24-nola.jpg

Figure 15: NOLA Theyyam and other artwork, seen in Treme.

2014-12-28-15-31-13-nola.jpg

Figure 16: Seen in The Historic New Orleans Collection.

2014-12-28-17-09-18-nola.jpg

Figure 17: Late lunch on Canal street.

• • •

2014-12-29-11-56-49-henry.jpg

Figure 18: Henry the baby alligator.

We took a swamp boat tour (one of the things you do when in New Orleans), where we met Henry the baby alligator.

Henry was with our swamp tour captain. Henry will be released to the swamp when he grows to about four and a half foot – as a young male, he is at the risk of being eaten by the big territorial alpha males. Our captain warned us not to mess with the part where he does his business – under his belly, between the hind legs, where the tail begins – or he might spray pee all over. He joked that they bottle that stuff in these parts and call it "gatorade."

December evidently is not the best time of the year to get to go meet the alligators in their natural habitat, but swamps themselves are very interesting, even when no alligators are in display.

• • •

2014-12-29-16-26-10-lsu.jpg

Figure 19: At LSU.

2014-12-30-17-19-32-tal.jpg

Figure 20: Thousand Acres Lake, Tennessee.

2014-12-30-17-26-03-tal.jpg

Figure 21: Thousand Acres Lake, Tennessee.

2014-12-31-15-04-49-indiana.jpg

Figure 22: Back in Indiana.

2014-12-31-17-12-31-rear-view-mirror.jpg

Figure 23: Rear view mirror.

I kept track of the route, in case if I ever feel like tracing it back someday.

We took I-69 to Indianapolis, stayed there for a night, and then headed south through the countryside: through the towns of Gosport, Spencer, Freedom, Worthington, Lyons, Westphalia, Edwardsport, Bucknell, and Evansville in Indiana; and Henderson, Dixon, Providence, Princeton, Cadiz, Land Between the Lakes National Recreation Area, Kenlake State Resort Park, Murray, and Hazel in Kentucky; Purear, Paris, Henry, Huntingdon, Lexington, Adamsville, and Selmor in Tennessee; Corinth, Shiloh Battlefield, Tuscumbia River (after which we drove on Natchez Trace Parkway for a few hundred miles, and stopped at French Camp Academy cafe for lunch), Kosciuszko, Carthage, Walnut Grove, Forest, Bienville National Forest, Raleigh, Mize ("home of watermelon festival"), Columbia ("city of charm of pearl river"), Ford House ("first house in pearl river valley") in Mississippi; entered LA 21S, and passed through Angie and a bunch of other towns which I missed to note down because it was dark by then; drove on Lake Pontchartrain Causeway (a world-record holding 38.35 km long bridge) to enter New Orleans.

On our way back home, we stopped at Louisiana State University in Baton Rouge, and then drove north: we passed Homochitto National Forest, Crosby, Vicksburg, Yazoo City, Morgan Break Wildlife Refuge, Matthew's Break Wildlife Refuge, Greenwood ("cotton capital of the world"), Malmaison Wildlife Management Area, Holcomb ("home of doodlebag festival"), Grenada (ate lunch at Grenada Southern City Cafe and Grill), Holly Springs Forest, Coffeeville, Water Valley, Oxford, Wal Doxey State Park, Holly Springs in Mississippi; Hickory Valley, Bolivar, Chicksaw State Park, Medon, Jackson, Thousand Acres Lakes, Huntingdon, Paris, Fort Danielson National Battlefield, Cross Creeks National Wildlife Refuge, and Clarksville in Tennessee; Homestead, Russellville, Morgantown ("catfish capital of the world"), Caneyville, Falls on the Rough (stayed at the Resort Inn, where folk spoke to us in thick rural Kentucky accent), Kingwood, Irvington (sent postcards to Bill from here), and Brandenburg in Kentucky; New Middleton (stopped at Log Cabin Cafe for breakfast), Crandall, Salem, Vallonia, Brownstone, (Indiana's Historic Pathways - North Spur), Seymour, Muskatatuk National Wildlife Refuge Hayden, (lunch at Fireside Pizza), Greensburg, Rushville, Spiceland, Newcastle, Muncie, Hartford City, Markle, and Ossian in Indiana, and finally home!

The round trip was around 1900 miles (3050 kms), and it was great fun.

• • •

I checked out New Orleans, Mon Amour: Twenty Years of Writings from the City by Andrei Codrescu from the library. Of New Orleans, Codrescu says:

Nostalgia is a full-time business in New Orleans, replete with manufactured glories, blessed by the chamber of commerce, and abetted by the cult of literary figures.

And:

It is easy to romanticize New Orleans – after all, dozens of writers, including Mark Twain, Walt Whitman, James Audubon, George Cable, and Lafcadio Hearn – did. They romanticized it down to its hideous summers, its muddy winters, its cutthroat streets, its gamblers, its crooked politicians, its whores. It was precisely from such corrupt gumbo that the dazzling flowers of its music – jazz, blues, Dixie – sprouted and dazzled the world. It was likewise with the telling and making of stories, the pageantry of Carnival, the complexity of dance, the subtleties of the palate. Hearing and admiring these fleurs the unwary tourist will sometime stumble into the living mud that feeds them.

And:

On the moonwalk by the river in downtown New Orleans, a saxophonist lets loose with a melancholy rendition of Charlie Parker’s “Mood.” A few tourists gawk at him misty-eyed because he fits exactly into that jazz-musician-shaped hole in their heads that they brought with them from the Midwest. In truth, the man isn’t bad. He’s loose, playful, and knows exactly what he’s dishing up. He’s a good-looking black man in his mid-fifties, with a salt-and-pepper beard. The sax case at his feet is stickered with European decals. He’s played Paris, Amsterdam, and Barcelona. The sax case is open and quickly filling with fives.

And:

We have always jokingly referred to New Orleans as part of the Third World, a foreign country in the United States. We didn't know how right we were. America either loves us or hates us. Those who love us love our music and food, a music and food that came from the depths of poverty and sorrow. The slaves sang spirituals to lift themselves up from pain and to get God’s ear. New Orleans jazz was born in whorehouses, another means of alleviating pain. This music told the stories of the poor who had no way out of New Orleans except for Jesus or gin. New Orleans has other arts, brought here by Spanish and French colonists, by pirates and renegades, by writers from other geographies of pain, and by Caribbean pagans. New Orleans has the most diverse spirituality in the whole of our quickly homogenizing states.

Did I just read a little contempt for visitors from the Midwest somewhere there? Perhaps I should feel insulted, even if I'm not quite "from" the Midwest?

January 24, 2015 06:00 AM

December 25, 2014

Daniil Frumin (notd)

ANN: Hastache version 0.6.1

Announcing: hastache 0.6.1

Happy holidays, everyone!

I would like to announce a new version of the Hastache library, version 0.6.1. Some interesting and useful changes, as well as improvements and bugfixes are included in the release. See below for an extended changelog.

Hastache is a Haskell implementation of the mustache templating system.

Quick start

cabal update
cabal install hastache

A simple example:

import Text.Hastache 
import Text.Hastache.Context 
import qualified Data.Text.Lazy.IO as TL

main = hastacheStr defaultConfig (encodeStr template) (mkStrContext context)
    >>= TL.putStrLn

template = "Hello, {{name}}!\n\nYou have {{unread}} unread messages." 

context "name" = MuVariable "Haskell"
context "unread" = MuVariable (100 :: Int)

Read Mustache documentation for template syntax; consult README for more details.

Whats’s new in 0.6.1?

Most of the new features in this release deal with generic contexts.

Context merging

composeCtx is a left-leaning composition of contexts. Given contexts c1 and c2, the behaviour of (c1 <> c2) x is following: if c1 x produces ‘MuNothing’, then the result is c2 x. Otherwise the result is c1 x. Even if c1 x is ‘MuNothing’, the monadic effects of c1 are still to take place.

Generic contexts for more datatypes

The mkGenericContext function now supports additional datatypes like Maybe (with Nothing being an empty/null value) and Either.

Context modifiers and renaming

The new mkGenericContext' is a generalized version of mkGenericContext and it takes two addition arguments. The first one, of type (String -> String) is simply a renaming function, similar to fieldLabelModifier of aeson. To see this feature in action, consider the following example:

{-# LANGUAGE DeriveDataTypeable #-}

import Text.Hastache 
import Text.Hastache.Context 

import qualified Data.Text.Lazy as TL 
import qualified Data.Text.Lazy.IO as TL 

import Data.Data (Data, Typeable)
import Data.Decimal
import Data.Generics.Aliases (extQ)

data Test = Test {f :: Int}
     deriving (Data, Typeable)

val1 :: Test
val1 = Test 1

val2 :: Test
val2 = Test 2

r "f" = "foo"
r x   = x

example :: Test -> IO TL.Text
example v = hastacheStr defaultConfig
                        (encodeStr template)
                        (mkGenericContext' r defaultExt v)

template = "An integer: {{foo}}"

main = do
  example val1 >>= TL.putStrLn
  example val2 >>= TL.putStrLn

In the example we use the renaming function r to rename a field “f” to “foo”.

The second additional argument is a query extension, of type Ext:

type Ext = forall b. (Data b, Typeable b) => b -> String

A query extension is a way of turning arbitrary datatypes into strings. This might come in very handy, if you want to generate mustache contexts from records/datatypes that contain non-primitive datatypes (from non-base modules) that you want to display. Before 0.6.1, if you had a record that contained, for example, a Decimal field, and you wanted to convert it to a context and access that field, you were simply out of luck. With this release you can basically extend the mkGenericContext' function to support any datatypes you want! Once again, I believe an example is worth a thousand words, so let us consider a slightly modified version of the example above:

{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}

-- Custom extension function for types that are not supported out of
-- the box in generic contexts
import Text.Hastache 
import Text.Hastache.Context 

import qualified Data.Text.Lazy as TL 
import qualified Data.Text.Lazy.IO as TL 

import Data.Data (Data, Typeable)
import Data.Decimal
import Data.Generics.Aliases (extQ)

data DecimalOrInf = Inf | Dec Decimal deriving (Data, Typeable)
deriving instance Data Decimal
data Test = Test {n::Int, m::DecimalOrInf} deriving (Data, Typeable)


val1 :: Test
val1 = Test 1 (Dec $ Decimal 3 1500)

val2 :: Test
val2 = Test 2 Inf

query :: Ext
query = defaultExt `extQ` f
  where f Inf = "+inf"
        f (Dec i) = show i

r "m" = "moo"
r x   = x

example :: Test -> IO TL.Text
example v = hastacheStr defaultConfig
                        (encodeStr template)
                        (mkGenericContext' r query v)

template = concat [ 
     "An int: {{n}}\n",
     "{{#moo.Dec}}A decimal number: {{moo.Dec}}{{/moo.Dec}}",
     "{{#moo.Inf}}An infinity: {{moo.Inf}}{{/moo.Inf}}"
     ] 

main = do
  example val1 >>= TL.putStrLn
  example val2 >>= TL.putStrLn

As you can see, the query extensions are combined using the extQ function from Data.Generics, and the “unit” of this whole thing is defaultExt function.

Links

Acknowledgments

This release would not have been possible without Tobias Florek, Edsko de Vries, Janne Hellsten, @clinty on Github, Stefan Kersten, Herbert Valerio Riedel, and other people who were submitting issues, patches, and requests.


Tagged: haskell, hastache

by Dan at December 25, 2014 12:49 PM

December 20, 2014

Sajith Sasidharan (sajith)

The Girl Nothing Happens To

Suppose you like reading cold war era sci-fi/fantasy from the old USSR. Suppose you have been pining for such a book to read this holiday season. Suppose you want to read the said book in Malayalam. Suppose you don't mind bootleg editions with totally questionable copyright ownership. I have you totally covered!

opape-cover.jpg

The Girl Nothing Happens To: Adventures of 21st-century Alice - Told by Her Father is a collection of short stories by Russian author Kirill Bulychyov (1934-2003, wikipedia article).

My 1984 copy of the Malayalam translation, published by Social Scientist Press, Trivandrum, is in tatters – it literally crumbles on touch. (Our thatched house in Wayanad leaked a lot during the rains. Our tiny bookshelf took some of the damage, so this was inevitable.) My father signed it with the date presumably on or around the time he bought it – December 15, 1984. It was translated to Malayalam by Abu – evidently so, because I lost that part of the book. It was sold at the royal price of 4 Indian Rupees.

opape-meta.jpg

I thought this translation should somehow live on, and so I'm trying to preserve this the way I best know. This effort is not authorized by the author or the translator.

I found an English translation here, translated from Russian by Gladys Evans, and published by Mir Publishers in 1973, with has different illustrations by another artist (Evgeni Tihonovich Migunov).

I could find pretty much nothing about Social Scientist Press in the Internet, except a reference to them in T M Thomas Isaac's CV: he evidently published The World Bank and IMF in 1998 with them. I have written to him to see if he knows whereabouts of anyone associated with Social Scientist Press. I have not heard anything back yet.

The USSR and Mir Publishers are now long gone; Kirill Bulychyov died in 2003; I would hazard a guess that Social Scientist Press is no longer in business, and that it is going to be really hard to find a translator whose name is simply "Abu".

Nevertheless, I would like to attribute this correctly and properly, and ask for forgiveness and/or permission from the rightful owners of this work. If you can help me trace back to them, please let me know!

The sources of my transcription lives in a friendly neighborhood git repository. If there is sufficient interest in this thing, I will try to post scans somewhere. If you find instances of glaring errors or misspellings, please let me know, or send patches or pull requests or whatever it is that the cool kids are up to these days.

Proceed to read: ഒന്നും പറ്റാത്ത പെണ്‍കുട്ടി.

December 20, 2014 06:00 AM

November 09, 2014

Clinton Ebadi (clinton)

I Improved A Thing

It does pretty much the same thing, better. Just need to practice soldering a bit more to turn it into a real circuit. And make the host program do something more interesting than the HSV color wheel.

by clinton at November 09, 2014 08:19 PM

October 24, 2014

Clinton Ebadi (clinton)

I made a thing

image

Master of electricity or something. I had meant to set up arduino controlled led strips in June…

by clinton at October 24, 2014 12:59 AM

October 05, 2014

Clinton Ebadi (clinton)