Browse Source

Initial import

applied-haskell
Michael Snoyman 7 years ago
parent
commit
22aba9df28
  1. BIN
      favicon.ico
  2. BIN
      img/blog.gif
  3. BIN
      img/book-cover.png
  4. BIN
      img/haskellers.png
  5. BIN
      img/luach.png
  6. BIN
      img/orangeroster.png
  7. BIN
      img/photoblog.png
  8. BIN
      img/profile.jpg
  9. BIN
      img/resume.png
  10. BIN
      img/yesodicon.png
  11. 137
      index.hamlet
  12. 12
      posts.yaml
  13. 1
      posts/first-post
  14. 76
      posts/ie-mimetype-png
  15. 14
      posts/xslt-rant
  16. 93
      posts/xslt-rant-explained
  17. 0
      robots.txt
  18. 437
      static/normalize.css
  19. 98
      static/style.lucius
  20. 61
      style.lucius
  21. 348
      torah/CFInstall.js
  22. 369
      torah/keinim2-2.html
  23. 156
      torah/teruma.html

BIN
favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
img/blog.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
img/book-cover.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
img/haskellers.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 B

BIN
img/luach.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 993 B

BIN
img/orangeroster.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

BIN
img/photoblog.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

BIN
img/profile.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
img/resume.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
img/yesodicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

137
index.hamlet

@ -0,0 +1,137 @@
$doctype 5
<html lang=en>
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Michael Snoyman's homepage
<link rel=stylesheet href=style.lucius>
<body>
<aside>
<img src=profile.jpg alt="Michael Snoyman" width=150 height=213>
<ul>
<li>
<a href="https://plus.google.com/116553865628071717889/posts">+Michael Snoyman
<li>
<a href="https://twitter.com/snoyberg">@snoyberg
<li>
<a href="http://www.haskellers.com/user/snoyberg">I'm a Haskeller
<div #twitter>
<a class="twitter-timeline" href="https://twitter.com/snoyberg" data-widget-id="296574273508741122">Tweets by @snoyberg</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
<article>
<h1>Michael Snoyman
<h2>About Me
<p .aboutme>
I'm a (mainly) Haskell web developer, and lead developer of the <a href="http://www.yesodweb.com">Yesod Web Framework</a>.
I'm the Lead Software Engineer at <a href="http://fpcomplete.com">FP Complete</a>.
I live in Maalot, Israel with my wife and three kids.
<h2>Publications
<ul>
<li>
<a href="http://aosabook.org/en/posa/warp.html">Performance of Open Source Applications#
. November 2013
<li>
<a href="http://www.aosabook.org/en/yesod.html">Architecture of Open Source Applications, Volume 2#
. May 2012
<li>
<a href="http://shop.oreilly.com/product/0636920023142.do">Developing Web Applications with Haskell and Yesod#
. April 2012, O'Reilly
<li>
<a href="http://steve.vinoski.net/pdf/IC-Warp_a_Haskell_Web_Server.pdf">Warp: A Haskell Web Server#
. June 2011, IEEE Spectrum
<i>The Functional Web
<h2>Talks
<table>
<thead>
<tr>
<th>Date
<th>Title
<th>Venue
<th>Links
<tbody>
<tr>
<td>October 2014
<td>Hybrid server/client Haskell web apps
<td>
<a href=http://polyconf.com/>PolyConf 2014
<td>To be posted after the talk
<tr>
<td>October 2014
<td>Conduit
<td>Haskell Users Group, Berlin
<td>To be posted after the talk
<tr>
<td>February 2014
<td>Pipes and Conduit
<td>Haskell Cast
<td>
<a href="http://www.haskellcast.com/episode/006-gabriel-gonzalez-and-michael-snoyman-on-pipes-and-conduit/">Video
<tr>
<td>November 2013
<td>Yesod and FP Complete
<td>Mostly Erlang (podcast)
<td>
<a href="http://mostlyerlang.com/2013/11/27/023-yesod-and-fp-complete/">Audio
<tr>
<td>October 2013
<td>Programming with Functional Style
<td>Erlang Factory, Tel Aviv
<td>
<a href="https://docs.google.com/presentation/d/1770ZKnm_bUpkOfzYN_IZq7AVFE6J1pKyFMX9iqVgyAI/edit?usp=sharing">Slides
<tr>
<td>Dec 2012
<td>Haskell and Yesod
<td>Sayeret Lambda
<td>
<a href="https://docs.google.com/presentation/d/1_A1QMbFPmpfBc-uJz8Z4G4tESVuxErW4kmI-R2yVnU4/edit">Slides
<tr>
<td>Dec 2012
<td>Yesod
<td>Floss Weekly
<td>
<a href="http://twit.tv/show/floss-weekly/236">Video
<tr>
<td>Nov 2012
<td>Designing Domain Specific Languages
<td>O'Reilly Webinar
<td>
<a href="http://www.oreillynet.com/pub/e/2400">Video
<a href="https://docs.google.com/presentation/d/1flkeCW-8rNPrT1d-YkxMm4repuAeT1YxjmdRd2f-FDs/edit">Slides
<tr>
<td>Oct 2012
<td>Yesod
<td>Sayeret Lambda (podcast)
<td>
<a href="http://narkisr.github.io/lambda-pod/posts/2012-10/lambda-pod-yesod-episode.html">Audio
<tr>
<td>June 2012
<td>Designing Type-Safe Haskell APIs
<td>Big Techday 5
<td>
<a href="http://www.oreillynet.com/pub/e/2351">Video
<a href="https://docs.google.com/presentation/d/1K7smIeqmca-fY8qgQUKrvWWHTUPJoKuVLRtLeWYFMtI/edit">Slides
<tr>
<td>Nov 2011
<td>Yesod Web Framework
<td>QCon San Francisco
<td>
<a href="http://www.infoq.com/presentations/Yesod;jsessionid=6AF0AA3EF8CCCE7195BDBBB0C8E1050B">Video
<a href="https://docs.google.com/presentation/d/15wN2uLhMdTWqvYD2RtN0W3XFyTYQ0Kh6bHOKlthBhX0/edit">Slides
<h2>My Sites
<ul>
<li>
<a href="http://photos.snoyman.com">Family Photo Blog
<li>
<a href="http://www.yesodweb.com">Yesod Web Framework
<li>
<a href="http://www.haskellers.com">Haskellers
<li>
<a href="http://packdeps.haskellers.com">Packdeps
<li>
<a href="http://luach.snoyman.com">Luach

12
posts.yaml

@ -0,0 +1,12 @@
- file: posts/xslt-rant-explained
title: "XSLT Rant Explained"
day: 2012-04-09
- file: posts/xslt-rant
title: "Open Letter to XSLT Fans"
day: 2012-04-05
- file: posts/ie-mimetype-png
title: "Dysfunctional Programming: FindMimeFromData"
day: 2012-03-22
- file: posts/first-post
title: First Post
day: 2012-01-31

1
posts/first-post

@ -0,0 +1 @@
Most of my blogging still occurs on the [Yesod blog](http://www.yesodweb.com/blog). This blog will be home for posts that are not necessarily Yesod or Haskell related.

76
posts/ie-mimetype-png

@ -0,0 +1,76 @@
I've been a bit torn about what exactly to put on this blog. Short comments go
to Google+. Anything Haskell related goes to the [Yesod blog](http://www.yesodweb.com/blog).
So what goes here?
For now, I've decided to start a series on dysfunctional programming. In other
words, horror stories from the non-Haskell world.
Today's tale begins with a strange bug report. One of our clients says that all
of the CSS changes we put on their server have suddenly disappeared. Which is
especially strange, because I don't have any write access to their production
server. There were two aspects to this report: bullets were missing, and the
title image didn't display in IE. By the way, there's a separate title image,
provided by the client, for each publication.
Forget about the bullets for now, that one wasn't interesting. The title image
was truly a conundrum. I started off by loading the output in Chrome. No
problem. Internet Explorer? Red X. At first I thought it was a URL mangling
issue. But when I tried moving the title image to a simple path on the system
and loading it up, it *still* displayed as a red X.
I started a local Warp server and accessed the site from there. No problem.
So... the file itself is correct, and the name of the file isn't the problem.
What's the issue? I spent a good 30 minutes looking for PNG bugs in IE.
Unfortunately, with IE's sordid history of PNG bugs, it was like looking for a
needle in a haystack. However, I saw one off-hand comment:
> Try right-clicking the image, choosing properties, and look at the type.
I tried it and, sure enough, the type was "Unknown," not "PNG". So it turns out
that when served from a web server, IE was delivered the correct mimetype via a
response header. But when opening from the local filesystem, it needs to detect
the mimetype automatically.
Looking at a file extension is too simple. IE needs to outsmart us. The
solution?
[FindMimeFromData](http://msdn.microsoft.com/en-us/library/ie/ms775147%28v=vs.85%29.aspx).
This wonderfully constructed function inspects the contents of the file in
question and determines the mimetype. For example, this nifty little program
will print the mimetype of the title.png file:
#include <urlmon.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
char buff[256];
LPWSTR out;
FILE *in = fopen("title.png", "rb");
fread(buff, 1, 256, in);
FindMimeFromData(NULL, NULL, buff, 256, NULL, FMFD_DEFAULT, &out, 0);
printf("%ls\n", out);
return 0;
}
The result? `image/pjpeg` of course! Never mind that that's an invalid mimetype, but the Win32 function is giving the __wrong mimetype for a PNG file__!!! I'm not quite certain how Microsoft screwed this up so royally. There's a very explicit set of bytes at the beginning of the file indicating that it's a PNG, and [imagesize-conduit](http://hackage.haskell.org/package/imagesize-conduit) detects it just fine:
import Data.Conduit
import Data.Conduit.Binary
import Data.Conduit.ImageSize
main :: IO ()
main = do
f <- runResourceT $ sourceFile "title.png" $$ sinkImageInfo
print f
In other words: Internet Explorer, since version 4, can't even display some
simple images.
I had to tell the client that we have no workaround, and they need to either
"fix" their perfectly valid PNG or always serve their content from a webserver.

14
posts/xslt-rant

@ -0,0 +1,14 @@
Dear XSLT fans,
Please don't insist on calling your bastard child of a language "functional." Just because it got one thing sort-of right (immutable data), doesn't mean that it in any way represents a real functional language.
I'm not even talking about the hideously verbose syntax, or the completely obtuse data model. The fact that you can't know what any single line of code does without reviewing __every other line in the program__ makes this language an abomination.
Don't believe me? Ask me for examples, I'll prove it. But anyone who's used XSLT for multi-file projects likely knows I'm right.
Oh, and the fact that you can call a language functional when it *lacks first class functions* makes my eye twitch. I'm tempted to upload a video of my eye twitching just to prove it.
Sincerely,
A Haskell programmer who spends an inordinate amount of time debugging bad XSLT.
PS: I would gladly write a program in Java, or C++, or likely assembly, over XSLT any day. Those languages may have issues, but they're sane tools. XSLT is just fundamentally broken.

93
posts/xslt-rant-explained

@ -0,0 +1,93 @@
My previous blog post got a bit more attention than I'd anticipated. I hadn't
really intended it as more than a place to link to and let the XSLT people I
work with know that the language isn't representative of functional languages.
However, a number of people have asked for more details. That's the purpose of
this post.
Before getting into the claims of my post itself, let me address some of the
counter-claims I saw in some of the discussions:
* <b>XSLT isn't *functional*, it's *declarative*.</b> I can agree with this distinction, and think the XSLT world needs to accept it.
* __XSLT is actually very concise.__ No, it's not. XPath- the query language used by XSLT- is incredibly concise, and I have no issue with it. In fact, when designing [xml-conduit](http://hackage.haskell.org/package/xml-conduit), Aristid and I designed the combinators after XPath.
* __XSLT 2.0 fixes a lot of this stuff.__ XSLT 2.0 is just lipstick on a hog. It changes none of the underlying problems.
One last bit of explanation: I don't think most people realize the level to
which XSLT is used in some projects. When used as a client-side technology to
convert some simple XML into simple HTML, XSLT can work just fine. I *still*
think it's a horrible language, but it's passable. The real problem is that
*XSLT doesn't scale*. Here's the issue I was alluding to in my previous blog
post. The DITA-OT has some code that looks like:
<!-- Copy @id attributes verbatim -->
<xsl:template match="@id">
<xsl:attribute name="id" select="."/>
</xsl:template>
<xsl:template match="some-element">
<xsl:apply-templates select="@id"/> <!-- Applies the default template to the ID attribute -->
<!-- A bunch more ugly code -->
</xsl:template>
Then, one of my coworkers unwittingly added:
<!-- Some special case requires printing out the attributes verbatim. -->
<xsl:template match="@*">
<xsl:if test="$some-special-case">
<xsl:value-of select="."/>
</xsl:if>
</xsl:template>
That second block says to print out the raw value of the attribute in question.
The problem is, it overrides the definition of the @id template in the first
block, and now all the ids for some-element are being printed out verbatim,
which is *not* what we wanted!
So which of those code blocks is wrong? Both of them. You shouldn't be
polluting the global namespace with these kinds of specific templates, they
each should have been put in their own `mode`. But I have two points here:
* `XSLT` is encouraging people to write bad code by using a global namespace by default.
* It's horribly difficult to find a bug like this. This project is well over 8000 lines of XSLT code, spread across some 40 files. It took me an hour to debug this. Sure, the people writing the original code wrote it badly, but a language shouldn't punish maintainers like this!
The issue here is one that many XSLT proponents contend is a strength: you can
go ahead and modify the behavior of existing templates in a later file. This
can actually be very convenient. Imagine you're converting DocBook to HTML, and
you have:
<xsl:template match="para">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
And now you decide that you would like to change this so that a `para` tag is
always given a `class` of `paragraph` in the HTML. You can go ahead and write a
customization:
<xsl:template match="para">
<p class="paragraph">
<xsl:apply-templates/>
</p>
</xsl:template>
And all of the existing code will automatically use this new template. I won't
argue that this isn't convenient. It certainly is. But it flies in the face of
all good engineering practice. Suddenly, I have no idea what an
`apply-templates` will do. I describe this as:
> You have no idea what a single line of code will do without analyzing every
> other line of code in your program.
There are plenty of ways to do this properly in real programming languages. In
my Haskell-based DITA processing code, for example, there is a setting allowing
you to specify specific handling for individual elements. Then in the calling
code, you are explicitly calling into a function for which you don't know what
the output will necessarily be. Everything is properly namespaced and
segregated, and you can know by looking at the code in front of you just how
it's going to be dispatched.
I'm out of time for now, but if anyone wants to see examples of XML processing
done right, let me know. I will say that for some of my company's newer
products, I've completely reimplemented DITA-to-HTML transforms, and it's
likely a tenth of the size of the DITA-OT's HTML transforms.

0
README → robots.txt

437
static/normalize.css

@ -0,0 +1,437 @@
/*! normalize.css 2012-01-22T23:30 UTC - http://github.com/necolas/normalize.css */
/* =============================================================================
HTML5 display definitions
========================================================================== */
/*
* Corrects block display not defined in IE6/7/8/9 & FF3
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section {
display: block;
}
/*
* Corrects inline-block display not defined in IE6/7/8/9 & FF3
*/
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
}
/*
* Prevents modern browsers from displaying 'audio' without controls
*/
audio:not([controls]) {
display: none;
}
/*
* Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4
* Known issue: no IE6 support
*/
[hidden] {
display: none;
}
/* =============================================================================
Base
========================================================================== */
/*
* 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units
* http://clagnut.com/blog/348/#c790
* 2. Prevents iOS text size adjust after orientation change, without disabling user zoom
* www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/
*/
html {
font-size: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/*
* Addresses font-family inconsistency between 'textarea' and other form elements.
*/
html,
button,
input,
select,
textarea {
font-family: sans-serif;
}
/*
* Addresses margins handled incorrectly in IE6/7
*/
body {
margin: 0;
}
/* =============================================================================
Links
========================================================================== */
/*
* Addresses outline displayed oddly in Chrome
*/
a:focus {
outline: thin dotted;
}
/*
* Improves readability when focused and also mouse hovered in all browsers
* people.opera.com/patrickl/experiments/keyboard/test
*/
a:hover,
a:active {
outline: 0;
}
/* =============================================================================
Typography
========================================================================== */
/*
* Neutralise smaller font-size in 'section' and 'article' in FF4+, Chrome, S5
*/
h1 {
font-size: 2em;
}
/*
* Addresses styling not present in IE7/8/9, S5, Chrome
*/
abbr[title] {
border-bottom: 1px dotted;
}
/*
* Addresses style set to 'bolder' in FF3+, S4/5, Chrome
*/
b,
strong {
font-weight: bold;
}
blockquote {
margin: 1em 40px;
}
/*
* Addresses styling not present in S5, Chrome
*/
dfn {
font-style: italic;
}
/*
* Addresses styling not present in IE6/7/8/9
*/
mark {
background: #ff0;
color: #000;
}
/*
* Corrects font family set oddly in IE6, S4/5, Chrome
* en.wikipedia.org/wiki/User:Davidgothberg/Test59
*/
pre,
code,
kbd,
samp {
font-family: monospace, serif;
_font-family: 'courier new', monospace;
font-size: 1em;
}
/*
* Improves readability of pre-formatted text in all browsers
*/
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
/*
* 1. Addresses CSS quotes not supported in IE6/7
* 2. Addresses quote property not supported in S4
*/
/* 1 */
q {
quotes: none;
}
/* 2 */
q:before,
q:after {
content: '';
content: none;
}
small {
font-size: 75%;
}
/*
* Prevents sub and sup affecting line-height in all browsers
* gist.github.com/413930
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* =============================================================================
Lists
========================================================================== */
ul,
ol {
margin-left: 0;
padding: 0 0 0 40px;
}
dd {
margin: 0 0 0 40px;
}
nav ul,
nav ol {
list-style: none;
list-style-image: none;
}
/* =============================================================================
Embedded content
========================================================================== */
/*
* 1. Removes border when inside 'a' element in IE6/7/8/9, FF3
* 2. Improves image quality when scaled in IE7
* code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/*
* Corrects overflow displayed oddly in IE9
*/
svg:not(:root) {
overflow: hidden;
}
/* =============================================================================
Figures
========================================================================== */
/*
* Addresses margin not present in IE6/7/8/9, S5, O11
*/
figure {
margin: 0;
}
/* =============================================================================
Forms
========================================================================== */
/*
* Corrects margin displayed oddly in IE6/7
*/
form {
margin: 0;
}
/*
* Define consistent border, margin, and padding
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/*
* 1. Corrects color not being inherited in IE6/7/8/9
* 2. Corrects text not wrapping in FF3
* 3. Corrects alignment displayed oddly in IE6/7
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
*margin-left: -7px; /* 3 */
}
/*
* 1. Corrects font size not being inherited in all browsers
* 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome
* 3. Improves appearance and consistency in all browsers
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
*vertical-align: middle; /* 3 */
}
/*
* Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet
*/
button,
input {
line-height: normal; /* 1 */
}
/*
* 1. Improves usability and consistency of cursor style between image-type 'input' and others
* 2. Corrects inability to style clickable 'input' types in iOS
* 3. Removes inner spacing in IE7 without affecting normal text inputs
* Known issue: inner spacing remains in IE6
*/
button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
cursor: pointer; /* 1 */
-webkit-appearance: button; /* 2 */
*overflow: visible; /* 3 */
}
/*
* 1. Addresses box sizing set to content-box in IE8/9
* 2. Removes excess padding in IE8/9
* 3. Removes excess padding in IE7
Known issue: excess padding remains in IE6
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
*height: 13px; /* 3 */
*width: 13px; /* 3 */
}
/*
* 1. Addresses appearance set to searchfield in S5, Chrome
* 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof)
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/*
* Removes inner padding and search cancel button in S5, Chrome on OS X
*/
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: none;
}
/*
* Removes inner padding and border in FF3+
* www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/*
* 1. Removes default vertical scrollbar in IE6/7/8/9
* 2. Improves readability and alignment in all browsers
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/* =============================================================================
Tables
========================================================================== */
/*
* Remove most spacing between table cells
*/
table {
border-collapse: collapse;
border-spacing: 0;
}

98
static/style.lucius

@ -0,0 +1,98 @@
@headercolor: #000;
html {
background-color: #ccf;
}
body {
font-family: Calibri, Helvetica, "Droid Sans", "DejaVu Sans", Verdana, sans-serif;
width: 940px;
margin: 1em auto;
padding: 1em;
background-color: #fff;
border: 1px solid #333;
}
header h1 {
margin-top: 0;
font-size: 1em;
font-weight: normal;
color: #{headercolor};
}
header {
border-bottom: 3px solid #000;
margin-bottom: 2em;
}
.sidebar h1 {
color: #{headercolor};
}
article {
width: 600px;
float: left;
}
article hgroup {
margin-bottom: 2em;
h1 {
margin: 0;
}
h2 {
font-size: 1em;
font-weight: normal;
font-style: italic;
margin: 0;
color: #666;
}
}
.sidebar {
width: 250px;
float: right;
font-size: 0.8em;
}
nav ul {
padding: 0;
}
.me p {
font-style: italic;
}
.sidebar > * {
border: 1px solid #333;
border-radius: 5px;
padding: 5px;
margin-bottom: 2em;
background-color: #fff8dd;
}
.sidebar h1 {
margin: 0;
}
.links li {
margin-bottom: 0.5em;
}
a, a:visited {
color: #00f;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.clearfix {
clear: both;
}
.book img {
width: 150px;
}
.archive section h1 {
font-size: 1em;
color: #000;
margin-top: 1em;
}
@media (max-width: 960px) {
body {
width: auto;
margin: 0;
}
article, .sidebar {
float: none;
}
article {
width: auto;
}
}

61
style.lucius

@ -0,0 +1,61 @@
html, body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
aside {
float: right;
width: 300px;
}
article {
margin-right: 320px;
}
body {
width: 900px;
margin: 0 auto;
}
p.aboutme {
white-space: pre-wrap;
}
table {
border-spacing: 0;
border-collapse: collapse;
}
tr:nth-child(odd) td {
background-color: #f8f8f8;
}
td {
font-size: 0.9em;
padding: 2px;
}
td:nth-child(2) {
font-weight: bold;
}
@media screen and (max-width: 900px) {
aside {
float: none;
width: auto;
}
#twitter {
display: none;
}
body {
width: auto;
margin: 5px;
}
article {
margin: 0;
}
}

348
torah/CFInstall.js

@ -0,0 +1,348 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview CFInstall.js provides a set of utilities for managing
* the Chrome Frame detection and installation process.
* @author slightlyoff@google.com (Alex Russell)
*/
(function(scope) {
// bail if we'd be over-writing an existing CFInstall object
if (scope['CFInstall']) {
return;
}
/**
* returns an item based on DOM ID. Optionally a document may be provided to
* specify the scope to search in. If a node is passed, it's returned as-is.
* @param {string|Node} id The ID of the node to be located or a node
* @param {Node} doc Optional A document to search for id.
* @return {Node}
*/
var byId = function(id, doc) {
return (typeof id == 'string') ? (doc || document).getElementById(id) : id;
};
/////////////////////////////////////////////////////////////////////////////
// Plugin Detection
/////////////////////////////////////////////////////////////////////////////
/**
* Checks to find out if ChromeFrame is available as a plugin
* @return {Boolean}
*/
var isAvailable = function() {
// For testing purposes.
if (scope.CFInstall._force) {
return scope.CFInstall._forceValue;
}
// Look for CF in the User Agent before trying more expensive checks
var ua = navigator.userAgent.toLowerCase();
if (ua.indexOf("chromeframe") >= 0) {
return true;
}
if (typeof window['ActiveXObject'] != 'undefined') {
try {
var obj = new ActiveXObject('ChromeTab.ChromeFrame');
if (obj) {
return true;
}
} catch(e) {
// squelch
}
}
return false;
};
/**
* Creates a style sheet in the document containing the passed rules.
*/
var injectStyleSheet = function(rules) {
try {
var ss = document.createElement('style');
ss.setAttribute('type', 'text/css');
if (ss.styleSheet) {
ss.styleSheet.cssText = rules;
} else {
ss.appendChild(document.createTextNode(rules));
}
var h = document.getElementsByTagName('head')[0];
var firstChild = h.firstChild;
h.insertBefore(ss, firstChild);
} catch (e) {
// squelch
}
};
/** @type {boolean} */
var cfStyleTagInjected = false;
/** @type {boolean} */
var cfHiddenInjected = false;
/**
* Injects style rules into the document to handle formatting of Chrome Frame
* prompt. Multiple calls have no effect.
*/
var injectCFStyleTag = function() {
if (cfStyleTagInjected) {
// Once and only once
return;
}
var rules = '.chromeFrameInstallDefaultStyle {' +
'width: 800px;' +
'height: 600px;' +
'position: absolute;' +
'left: 50%;' +
'top: 50%;' +
'margin-left: -400px;' +
'margin-top: -300px;' +
'}' +
'.chromeFrameOverlayContent {' +
'position: absolute;' +
'margin-left: -400px;' +
'margin-top: -300px;' +
'left: 50%;' +
'top: 50%;' +
'border: 1px solid #93B4D9;' +
'background-color: white;' +
'}' +
'.chromeFrameOverlayContent iframe {' +
'width: 800px;' +
'height: 600px;' +
'border: none;' +
'}' +
'.chromeFrameOverlayCloseBar {' +
'height: 1em;' +
'text-align: right;' +
'background-color: #CADEF4;' +
'}' +
'.chromeFrameOverlayUnderlay {' +
'position: absolute;' +
'width: 100%;' +
'height: 100%;' +
'background-color: white;' +
'opacity: 0.5;' +
'-moz-opacity: 0.5;' +
'-webkit-opacity: 0.5;' +
'-ms-filter: ' +
'"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";' +
'filter: alpha(opacity=50);' +
'}';
injectStyleSheet(rules);
cfStyleTagInjected = true;
};
/**
* Injects style rules to hide the overlay version of the GCF prompt.
* Multiple calls have no effect.
*/
var closeOverlay = function() {
// IE has a limit to the # of <style> tags allowed, so we avoid
// tempting the fates.
if (cfHiddenInjected) {
return;
}
var rules = '.chromeFrameOverlayContent { display: none; }' +
'.chromeFrameOverlayUnderlay { display: none; }';
injectStyleSheet(rules);
// Hide the dialog for a year (or until cookies are deleted).
var age = 365 * 24 * 60 * 60 * 1000;
document.cookie = "disableGCFCheck=1;path=/;max-age="+age;
cfHiddenInjected = true;
};
/**
* Plucks properties from the passed arguments and sets them on the passed
* DOM node
* @param {Node} node The node to set properties on
* @param {Object} args A map of user-specified properties to set
*/
var setProperties = function(node, args) {
var srcNode = byId(args['node']);
node.id = args['id'] || (srcNode ? srcNode['id'] || getUid(srcNode) : '');
// TODO(slightlyoff): Opera compat? need to test there
var cssText = args['cssText'] || '';
node.style.cssText = ' ' + cssText;
var classText = args['className'] || '';
node.className = classText;
// default if the browser doesn't so we don't show sad-tab
var src = args['src'] || 'about:blank';
node.src = src;
if (srcNode) {
srcNode.parentNode.replaceChild(node, srcNode);
}
};
/**
* Creates an iframe.
* @param {Object} args A bag of configuration properties, including values
* like 'node', 'cssText', 'className', 'id', 'src', etc.
* @return {Node}
*/
var makeIframe = function(args) {
var el = document.createElement('iframe');
el.setAttribute('frameborder', '0');
el.setAttribute('border', '0');
setProperties(el, args);
return el;
};
/**
* Adds an unadorned iframe into the page, taking arguments to customize it.
* @param {Object} args A map of user-specified properties to set
*/
var makeInlinePrompt = function(args) {
args.className = 'chromeFrameInstallDefaultStyle ' +
(args.className || '');
var ifr = makeIframe(args);
// TODO(slightlyoff): handle placement more elegantly!
if (!ifr.parentNode) {
var firstChild = document.body.firstChild;
document.body.insertBefore(ifr, firstChild);
}
};
/**
* Adds a styled, closable iframe into the page with a background that
* emulates a modal dialog.
* @param {Object} args A map of user-specified properties to set
*/
var makeOverlayPrompt = function(args) {
if (byId('chromeFrameOverlayContent')) {
return; // Was previously created. Bail.
}
var n = document.createElement('span');
n.innerHTML = '<div class="chromeFrameOverlayUnderlay"></div>' +
'<table class="chromeFrameOverlayContent"' +
'id="chromeFrameOverlayContent"' +
'cellpadding="0" cellspacing="0">' +
'<tr class="chromeFrameOverlayCloseBar">' +
'<td>' +
// TODO(slightlyoff): i18n
'<button id="chromeFrameCloseButton">close</button>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td id="chromeFrameIframeHolder"></td>' +
'</tr>' +
'</table>';
document.body.appendChild(n);
var ifr = makeIframe(args);
byId('chromeFrameIframeHolder').appendChild(ifr);
byId('chromeFrameCloseButton').onclick = closeOverlay;
};
var CFInstall = {};
/**
* Checks to see if Chrome Frame is available, if not, prompts the user to
* install. Once installation is begun, a background timer starts,
* checkinging for a successful install every 2 seconds. Upon detection of
* successful installation, the current page is reloaded, or if a
* 'destination' parameter is passed, the page navigates there instead.
* @param {Object} args A bag of configuration properties. Respected
* properties are: 'mode', 'url', 'destination', 'node', 'onmissing',
* 'preventPrompt', 'oninstall', 'preventInstallDetection', 'cssText', and
* 'className'.
* @public
*/
CFInstall.check = function(args) {
args = args || {};
// We currently only support CF in IE
// TODO(slightlyoff): Update this should we support other browsers!
var ua = navigator.userAgent;
var ieRe = /MSIE \S+; Windows NT/;
var bail = false;
if (ieRe.test(ua)) {
// We also only support Win2003/XPSP2 or better. See:
// http://msdn.microsoft.com/en-us/library/ms537503%28VS.85%29.aspx
if (parseFloat(ua.split(ieRe)[1]) < 6 &&
ua.indexOf('SV1') < 0) {
bail = true;
}
} else {
bail = true;
}
if (bail) {
return;
}
// Inject the default styles
injectCFStyleTag();
if (document.cookie.indexOf("disableGCFCheck=1") >=0) {
// If we're supposed to hide the overlay prompt, add the rules to do it.
closeOverlay();
}
// When loaded in an alternate protocol (e.g., "file:"), still call out to
// the right location.
var currentProtocol = document.location.protocol;
var protocol = (currentProtocol == 'https:') ? 'https:' : 'http:';
// TODO(slightlyoff): Update this URL when a mini-installer page is
// available.
var installUrl = protocol + '//www.google.com/chromeframe';
if (!isAvailable()) {
if (args.onmissing) {
args.onmissing();
}
args.src = args.url || installUrl;
var mode = args.mode || 'inline';
var preventPrompt = args.preventPrompt || false;
if (!preventPrompt) {
if (mode == 'inline') {
makeInlinePrompt(args);
} else if (mode == 'overlay') {
makeOverlayPrompt(args);
} else {
window.open(args.src);
}
}
if (args.preventInstallDetection) {
return;
}
// Begin polling for install success.
var installTimer = setInterval(function() {
// every 2 seconds, look to see if CF is available, if so, proceed on
// to our destination
if (isAvailable()) {
if (args.oninstall) {
args.oninstall();
}
clearInterval(installTimer);
// TODO(slightlyoff): add a way to prevent navigation or make it
// contingent on oninstall?
window.location = args.destination || window.location;
}
}, 2000);
}
};
CFInstall._force = false;
CFInstall._forceValue = false;
CFInstall.isAvailable = isAvailable;
// expose CFInstall to the external scope. We've already checked to make
// sure we're not going to blow existing objects away.
scope.CFInstall = CFInstall;
})(this['ChromeFrameInstallScope'] || this);

369
torah/keinim2-2.html

@ -0,0 +1,369 @@
<!DOCTYPE html>
<html>
<head>
<title>Keinim</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<style>
body {
background-color: #cff;
font-family: sans-serif;
}
p {
line-height: 140%;
}
#wrapper {
background-color: #ffc;
width: 700px;
padding: 1em;
margin: 1em auto;
border: 1px solid black;
-moz-border-radius: 10px;
-moz-box-shadow: 2px 2px 1px 1px;
-webkit-border-radius: 10px;
-webkit-box-shadow: 2px 2px 1px #000;
}
h1 {
text-align: center;
color: #090;
}
h2 {
text-align: center;
color: #603;
}
.birds {
text-align: center;
}
.birds h5 {
margin: 0 0 5px 0;
text-decoration: underline;
}
.birds > div {
display: inline-block;
_display: inline;
border: 1px solid black;
margin-right: 1em;
text-align: center;
padding: 0 15px;
-moz-box-shadow: 1px 1px 1px;
-webkit-box-shadow: 1px 1px #000;
}
.birds > div > div {
width: 15px;
height: 15px;
display: inline-block;
_display: inline;
border: 1px solid #000;
}
.leah {
background-color: #f00;
}
.rachel {
background-color: #0f0;
}
.birds > div > div.none {
background-color: #999;
width: 11px;
height: 11px;
}
.leah.none {
border: 3px solid #f00;
}
.rachel.none {
border: 3px solid #0f0;
}
.olah {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
</style>
</head>
<body>
<script type="text/javascript" src="CFInstall.js"></script>
<script>CFInstall.check();</script>
<div id="wrapper">
<h1>Masechet Keinim 2:2</h1>
<h2>L'iluy nishmat Iser ben Binyamin HaCohen<br>
לעילוי נשמת איסר בן בנימין הכהן</h2>
<p>This d'var Torah is to mark my siyum- completion- of the fifth order of the mishna, Seder Kodshim, in memory of my grandfather Iser ben Binyamin HaCohen. Kodshim is paricularly appropriate, as it describes the intricacies of the temple service, from the details of an offering to the measurements of the temple mount.</p>
<p>The Mishna is broken up into six <i>sedarim</i>, or orders. Each order is divided into a number of <i>masechtot</i>, or tractates. The last tractate is called <i>keinim</i>, which literally means nests. It refers to the bird offerings in the temple. I would like to touch on one topic in this tractate.</p>
<h3>Pairs</h3>
<p>The most common case for bringing a bird offering was a birth, and thus the entire tractate refers to the owner of the birds in the feminine. For each birth, a woman was required to bring a <b>pair</b> of birds, one as an <i>olah</i> (burnt offering) and one as a <i>chatat</i> (sin offering).</p>
<p>I stress pair here because these birds <b>must</b> go together; it is not sufficient to have two separate bird offerings. They must be brought to the temple as a pair, and if the first is designated an olah, the other is automatically a chatat, and vice versa.</p>
<h3>Keinim 2:2</h3>
<blockquote>Two women: Rachel has two pairs of birds, and Leah has two pairs. If one of Rachel's birds flies and is mixed in with Leah's birds, the bird invalidates one in its departure. If one returns (from Leah to Rachel), it invalidates one in its return.</blockquote>
<p>I chose this Mishna because it has a very mathematical nature to it, something I feel connects me with my grandfather. In particular, this branch of math is known as combinatorics, or studying different possible combinations. In order to understand what's going on, let's look at a simpler case.</p>
<h3>Four birds</h3>
<h4>No funny business</h4>
<p>Let's say that Rachel has a single pair of birds, as does Leah. If none of the birds do any funny business, one of Rachel's birds will be an olah, and one will be a chatat. The same is true of Leah's birds. It would look like this:</p>
<div class="birds">
<div>
<h5>Rachel</h5>
<div class="rachel chatat"></div>
<div class="rachel olah"></div>
</div>
<div>
<h5>Leah</h5>
<div class="leah chatat"></div>
<div class="leah olah"></div>
</div>
</div>
<h4>OK, some funny busines</h4>
<p>Now let's say one of the birds decides to become Houdini (another Cohen if I'm not mistaken). One of Rachel's birds hops the fence into Leah's cage, and now we don't know whose bird is whose. Once a bird is assigned an owner, the owner cannot be changed (in the picture, color represents the owner). However, the <i>type</i> of offering (circle for olah and square for chatat) has <i>not</i> been assigned, and is thus up for grabs.</p>
<p>It's not possible for us to make more than two birds a chatat or more than two an olah, so the best case scenario would be that two of the three birds in Leah's possession will be an olah, the third will be a chatat, and the single bird in Rachel's cage will also be a chatat. That would look like this:</p>
<div class="birds">
<div>
<h5>Rachel</h5>
<div class="rachel chatat"></div>
</div>
<div>
<h5>Leah</h5>
<div class="leah chatat"></div>
<div class="leah olah"></div>
<div class="rachel olah"></div>
</div>
</div>
<p>In this case, all is fine and dandy; Leah's pair (the red birds) are an olah and chatat, and Rachel's pair (the green ones) are also an olah and chatat. No problem.</p>
<p>However, this assumes that we guessed correctly. Since the bird in Rachel's cage is a chatat, then we need to make sure that the green bird in Leah's cage is an olah, since we need matching pairs. We don't really know which bird actually belongs to Rachel, so we could accidently do the following:</p>
<div class="birds">
<div>
<h5>Rachel</h5>
<div class="rachel chatat"></div>
</div>
<div>
<h5>Leah</h5>
<div class="rachel chatat"></div>
<div class="leah olah"></div>
<div class="leah olah"></div>
</div>
</div>
<p>Now we've got a real problem! Both of Rachel's birds are chatats, and both of Leah's birds are olahs. We've got no matching pairs at all, so none of the offerings were good. It turns out the best we can do, mathematically, is to offer just two of the birds from Leah's cage. Here's the possibilities:</p>
<ul>
<li>The two birds that are chosen actually belong to Leah. Then Leah had a full offering of an olah and chatat, and Rachel gets nothing.
<div class="birds">
<div>
<h5>Rachel</h5>
<div class="rachel none"></div>
</div>
<div>
<h5>Leah</h5>
<div class="leah chatat"></div>
<div class="leah olah"></div>
<div class="rachel none"></div>
</div>
</div>
</li>
<li>One of the chosen birds is Leah's and one is Rachel's. Each of them will get a single offering (it could go either way, it doesn't really matter). But at least there are no mis-matched pairs.
<div class="birds">
<div>
<h5>Rachel</h5>
<div class="rachel none"></div>
</div>
<div>
<h5>Leah</h5>
<div class="leah chatat"></div>
<div class="rachel olah"></div>
<div class="leah none"></div>
</div>
</div>
</li>
</ul>
<h3>Eight birds</h3>
<p>Well, eight birds is basically the exact same things as four, just more complicated. To look at this mathematically, our goal is to understand:</p>
<ul>
<li>Why making any more sacrifices than specified by the mishna could lead to mismatched pairs.</li>
<li>Why there is no possibility of mismatched pairs with the solution of the mishna.</li>
</ul>
<p>Proving the first is easier: we need a counter-example, or a case that <i>could</i> lead to mismatched pairs. Let's start off with the base case: one of Rachel's birds flew into Leah's cage:</p>
<div class="birds">
<div>
<h5>Rachel</h5>
<div class="rachel none"></div>
<div class="rachel none"></div>
<div class="rachel none"></div>
</div>
<div>
<h5>Leah</h5>
<div class="leah none"></div>
<div class="leah none"></div>
<div class="leah none"></div>
<div class="leah none"></div>
<div class="rachel none"></div>
</div>
</div>
<h4>Doing it wrong</h4>
<p>The mishna says that this disqualifies one of Rachel's birds, meaning that we sacrifice four from Leah's cage and two from Rachel's. There are two ways to sacrifice more than the allowed number:</p>
<ul>
<li>
<p>We could sacrifice three from Rachel's cage instead of two. However, this could lead to a problem if we had something like the following:</p>
<div class="birds">
<div>
<h5>Rachel</h5>
<div class="rachel chatat"></div>
<div class="rachel olah"></div>
<div class="rachel olah"></div>
</div>
<div>
<h5>Leah</h5>
<div class="leah chatat"></div>
<div class="leah olah"></div>
<div class="leah chatat"></div>
<div class="leah none"></div>
<div class="rachel olah"></div>
</div>
</div>
<p>That is, we sacrifice two olahs from Rachel's cage, and then inadvertently sacrifice Rachel's bird in Leah's cage as an olah. This means that, in total, we would have three olahs and one chatat for Rachel, which is unmatched.</p>
</li>
<li>
<p>We could sacrifice five from Leah's cage instead of four. Here the problem would be:</p>
<div class="birds">
<div>
<h5>Rachel</h5>
<div class="rachel chatat"></div>
<div class="rachel olah"></div>
<div class="rachel none"></div>
</div>
<div>
<h5>Leah</h5>
<div class="leah chatat"></div>
<div class="leah olah"></div>
<div class="leah chatat"></div>
<div class="leah chatat"></div>
<div class="rachel olah"></div>
</div>
</div>
<p>Here, the problem is that we might accidently sacrifice three of Leah's birds as the same type of offering. This would also be mismatched.</p>
</li>
</ul>
<h4>Doing it right</h4>
<p>So how do we know that the mishna's advice works? Well, let's do some deductive reasoning. Rachel has four birds all told. If she sacrifices two of them in her cage as a pair, she still has one left over to be the pair to the one in Leah's cage. If we don't sacrifice that third bird, then the fourth has the freedom to be anything it wants (within the realm of dead birds).</p>
<div class="birds">
<div>
<h5>Rachel</h5>
<div class="rachel olah"></div>
<div class="rachel chatat"></div>
<div class="rachel none"></div>
</div>
<div>
<h5>Leah</h5>
<div class="leah none"></div>
<div class="leah none"></div>
<div class="leah none"></div>
<div class="leah none"></div>
<div class="rachel none"></div>
</div>
</div>
<p>That means that if Leah sacrifices Rachel's bird as either an olah or chatat, or doesn't sacrifice any of Rachel's birds, we're safe. <b>There is nothing we can do to mess up Rachel's offerings.</b> The only concern is Leah's offerings.</p>
<p>Well, if we offer four of the birds in Leah's cage, there are two possibilies:</p>
<ol>
<li>One of the birds offered was Rachel's escapee, and one of Leah's birds was left out.</li>
<li>All four birds belonged to Leah, and Rachel's bird was left out.</li>
</ol>
<p>In option 1, Leah gets one matched pair and one lone offering, while Rachel gets an offering without a pair. Cool. In option 2, Leah gets two matched pairs, and Rachel gets nothing. Also good.</p>
<h3>The grass is greener on the other side</h3>
<p>Still with me? Good, we're right at the end here. So here goes the story: one of Rachel's birds flies into Leah's cage, and realizes living conditions were much better in Rachel's cage. The bird starts complaining, and eventually <i>some</i> bird flies into Rachel's cage. Problem is, we don't know if it was Rachel's escapee, or if one of Leah's birds has now broken out of jail.</p>
<p>What makes this different is <b>we have two possible base cases</b>, as follows:</p>
<ol>
<li>
<div class="birds">
<div>