text:
Calculating expectation by plugging into the definition works in simple cases, but often it can be cumbersome or lack insight. The most powerful result for calculating expectation turns out not to be the definition. It looks rather innocuous:

Let $X$ and $Y$ be two random variables defined on the same probability space. Then

$$E(X+Y) = E(X) + E(Y)$$

Before we look more closely at this result, note that we are assuming that all the expectations exist; we will do this throughout in this course.

And now note that there are no assumptions about the relation between $X$ and $Y$. They could be dependent or independent. Regardless, the expectation of the sum is the sum of the expectations. This makes the result powerful.

Additivity follows easily from the definition of $X+Y$ and the definition of expectation on the domain space. First note that the random variable $X+Y$ is the function defined by

$$(X+Y)(\omega) = X(\omega) + Y(\omega) ~~~~ \text{for all } \omega \in \Omega$$

Thus a "value of $X+Y$ weighted by the probability" can be written as

$$(X+Y)(\omega) \cdot P(\omega) = X(\omega)P(\omega) + Y(\omega)P(\omega )$$

Sum the two sides over all $\omega \in \Omega$ to prove additivty of expecation.

By induction, additivity extends to any finite number of random variables. If $X_1, X_2, \ldots , X_n$ are random variables defined on the same probability space, then

$$E(X_1 + X_2 + \cdots + X_n) = E(X_1) + E(X_2) + \cdots + E(X_n)$$

If you are trying to find an expectation, then the way to use additivity is to write your random variable as a sum of simpler variables whose expectations you know or can calculate easily. The rest of this section consists of examples of this technique.

Sample Sum

Let $X_1, X_2, \ldots , X_n$ be a sample drawn at random from a numerical population that has mean $\mu$, and let the sample sum be $$S_n = X_1 + X_2 + \cdots + X_n$$ Then, regardless of whether the sample was drawn with or without replacement, each $X_i$ has the same distribution as the population. This is clearly true if the sampling is with replacement, and it is true by symmetry if the sampling is without replacement as we saw in an earlier chapter.

So, regardless of whether the sample is drawn with or without replacement, $E(X_i) = \mu$ for each $i$, and hence

$$E(S_n) = E(X_1) + E(X_2) + \cdots + E(X_n) = n\mu$$

Linear Function Rule

Let $X$ be a random variable with expectation $E(X)$ and let $Y = aX$ for some constant $a$. For example, when you change units of a random length from inches to centimeters, then $a = 2.54$.

For every $\omega \in \Omega$, we have $Y(\omega) = aX(\omega)$. So

$$E(Y) ~ = ~ \sum_{\text{all }\omega} aX(\omega)P(\omega) ~ = ~a \sum_{\text{all }\omega} X(\omega)P(\omega ) ~ = ~ aE(X)$$

Now consider the linear tranformation $W = aX + b$. This kind of transformation happens for example when you change units from Celsius to Fahreneheit. In that case $a = 9/5$ and $b = 32$.

Then $W = Y + b$, so by additivity of expectation,

$$E(W) = E(aX + b) = E(aX) + E(b) = aE(X) + b$$

So for example, $E(2X - 3) = 2E(X) - 3$. Also $E(X/2) = E(X)/2$, and $E(1 - X) = 1 - E(X)$.

The expectation of a linear transformation of $X$ is the linear transformation of the expectation of $X$. This is a handy result as we will often be transforming variables linearly. But expectation behaves differently under non-linear transformations, as we will see in the next section.

Example: An Unbiased Estimator

Suppose $\theta$ is a parameter of the distribution of $X$, and suppose $E(X) = \theta$. Then we say that $X$ is an unbiased estimator of $\theta$.

If an estimator is unbiased, and you use it to generate estimates repeatedly and independently, then in the long run the average of all the estimates is equal to the parameter being estimated. On average, the unbiased estimator is neither higher nor lower than the parameter. That's usually considered a good quality in an estimator.

As in the sample sum example above, let $S_n$ be the sum of a sample of size $n$ drawn from a population that has mean $\mu$. Let $A_n$ be the sample average, that is,

$$A_n = \frac{S_n}{n}$$

Then, regardless of whether the draws were made with replacement or without,

\begin{align*} E(A_n) &= \frac{E(S_n)}{n} ~~~~ \text{(linear function rule)} \\ &= \frac{n \mu}{n} ~~~~~~~~~ \text{(} E(S_n) = n\mu \text{)} \\ &= \mu \end{align*}

Thus the sample mean is an unbiased estimator of the population mean.

Suppose we have a sample $X_1, X_2, \ldots , X_n$ where each variable is uniform on $1, 2, \ldots , N$ for some fixed $N$, and we are trying to estimate $N$. This was the setting in the German warplanes example in Data 8. The expectation of each of the uniform variables is $(N+1)/2$, as we have seen earlier. So if $A_n$ is the sample mean, then

$$E(A_n) = \frac{N+1}{2}$$

and so $A_n$ is not an unbiased estimator of $N$. That's not surprising because $N$ is the maximum possible value of each observation and $A_n$ should be somewhere in the middle of all the possible values.

But because $E(A_n)$ is a linear function of $N$, we can tweak $A_n$ to create an unbiased estimator of $N$. We just have to invert the linear function. Let $A_n^* = 2A_n - 1$. Then

$$E(A_n^*) = 2E(A_n) - 1 = 2 \cdot \frac{N+1}{2} - 1 = N$$

so $A_n^*$ is an unbiased estimator of $N$.

The Method of Indicators

This is a powerful method for finding expected counts. It is based on the observation that among $n$ trials, the number of "good" results can be counted by first coding each "good" result as 1 and each of the other results as 0, and then adding the 1's and 0's.

If $N$ is the total number of good results among $n$, then

$$N = I_1 + I_2 + \cdots + I_n$$

where for each $j$ in the range 1 through $n$, $I_j$ is the indicator of "the result of the $j$th trial is good". So

\begin{align*} E(N) &= E(I_1) + E(I_2) + \cdots + E(I_n) \\ &= P(\text{result of Trial } 1 \text{ is good}) + P(\text{result of Trial } 2 \text{ is good}) + \cdots + P(\text{result of Trial } n \text{ is good}) \\ \end{align*}

The additivity works regardless of whether the trials are dependent or independent.

We conclude this section with three applications of the method of indicators.

Example: Binomial

Let $X$ have the binomial $(n, p)$ distribution. Then $X$ can be thought of as the number of successes in $n$ i.i.d. Bernoulli $(p)$ trials, and we can write

$$X = I_1 + I_2 + \cdots + I_n$$

where for each $j$ in the range 1 through $n$, $I_j$ is the indicator of "Trial $j$ is a success". Thus

\begin{align*} E(X) &= E(I_1) + E(I_2) + \cdots + E(I_n) ~~~~ \text{(additivity)} \\ &= np ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \text{(}E(I_j) = p \text{ for all } j \text{)} \end{align*}

Examples of use:

• The expected number of heads in 100 tosses of a coin is $100 \times 0.5 = 50$.
• The expected number of heads in 25 tosses is 12.5. Remember that the expectation of an integer-valued random variable need not be an integer.
• The expected number of times green pockets win in 20 independent spins of a roulette wheel is $20 \times \frac{2}{38} = 1.053$, roughly.
k = np.arange(11)
probs = stats.binom.pmf(k, 10, 0.75)
bin_10_75 = Table().values(k).probability(probs)
Plot(bin_10_75, show_ev=True)
plt.title('Binomial (10, 0.75)');

Notice that we didn't use independence. Additivity of expectation works whether or not the random variables being added are independent. This will be very helpful in the next example.

Example: Hypergeometric

Let $X$ have the hypergeometric $(N, G, n)$ distribution. Then $X$ can be thought of as the number of good elements in $n$ draws made at random without replacement from a population of $N = G+B$ elements of which $G$ are good and $B$ bad. Then

$$X = I_1 + I_2 + \cdots + I_n$$

where for each $j$ in the range 1 through $n$, $I_j$ is the indicator of "Draw $j$ results in a good element". Thus

\begin{align*} E(X) &= E(I_1) + E(I_2) + \cdots + E(I_n) ~~~~ \text{(additivity)} \\ \\ &= n\frac{G}{N} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \text{(}E(I_j) = \frac{G}{N} \text{ for all } j \text{ by symmetry)} \end{align*}

This is the same answer as for the binomial, with the population proportion of good elements $G/N$ replacing $p$.

Examples of use:

• The expected number of red cards in a bridge hand of 13 cards is $13 \times \frac{26}{52} = 6.5$.
• The expected number of Independent voters in a simple random sample of 200 people drawn from a population in which 10% of the voters are Independent is $200 \times 0.1 = 20$.

These answers are intuitively clear, and we now have a theoretical justification for them.

# Number of hearts in a poker hand
N = 52
G = 13
n = 5
k = np.arange(6)
probs = stats.hypergeom.pmf(k, N, G, n)
hyp_dist = Table().values(k).probability(probs)
Plot(hyp_dist, show_ev=True)
plt.title('Hypergeometric (N=52, G=13, n=5)');

Example: Number of Missing Classes

A population consists of four classes of individuals, in the proportions 0.4, 0.3, 0.2, and 0.1. A random sample of $n$ individuals is chosen so that the choices are mutually independent. What is the expected number of classes that are missing in the sample?

If $M$ is the number of missing classes, then

$$M = I_1 + I_2 + I_3 + I_4$$

where for each $j$, $I_j$ is the indicator of "Class $j$ is missing in the sample".

For Class $j$ to be missing in the sample, all $n$ selected individuals have to be from the other classes. Thus

$$E(M) = E(I_1) + E(I_2) + E(I_3) + E(I_4) = 0.6^n + 0.7^n + 0.8^n + 0.9^n$$

The four indicators aren't independent but that doesn't affect the additivity of expectation.


text:
### 统计代写|数值分析和优化代写numerical analysis and optimazation代考|Cholesky Factorization

statistics-lab™ 为您的留学生涯保驾护航 在代写数值分析和优化numerical analysis and optimazation方面已经树立了自己的口碑, 保证靠谱, 高质且原创的统计Statistics代写服务。我们的专家在代写数值分析和优化numerical analysis and optimazation方面经验极为丰富，各种代写数值分析和优化numerical analysis and optimazation相关的作业也就用不着说。

• Statistical Inference 统计推断
• Statistical Computing 统计计算
• (Generalized) Linear Models 广义线性模型
• Statistical Machine Learning 统计机器学习
• Longitudinal Data Analysis 纵向数据分析
• Foundations of Data Science 数据科学基础

## 统计代写|数值分析和优化代写numerical analysis and optimazation代考|Cholesky Factorization

Let $A$ be an $n \times n$ symmetric matrix, i.e., $A_{i, j}=A_{j, i}$. We can take advantage of the symmetry by expressing $A$ in the form of $A=L D L^{T}$ where $L$ is lower triangular with ones on its diagonal and $D$ is a diagonal matrix. More explicitly, we can write the factorization which is known as Cholesky factorization as
$$A=\left(\begin{array}{lll} \mathbf{l}{1} & \ldots & \mathbf{l}{n} \end{array}\right)\left(\begin{array}{cccc} D_{1,1} & 0 & \cdots & 0 \ 0 & D_{2,2} & \ddots & \vdots \ \vdots & \ddots & \ddots & 0 \ 0 & \cdots & 0 & D_{n, n} \end{array}\right)\left(\begin{array}{c} \mathbf{l}{1}^{T} \ 1{2}^{T} \ \vdots \ 1_{n}^{T} \end{array}\right)=\sum_{k=1}^{n} D_{k, k} \mathbf{l}{k} 1{k}^{T}$$
Again $l_{k}$ denotes the $k^{\text {th }}$ column of $L$. The analogy to the LU algorithm is obvious when letting $U=D L^{T}$. However, this algorithm exploits the symmetry and requires roughly half the storage. To be more specific, we let $A_{0}=A$ at the beginning and for $k=1, \ldots, n$ we let $1_{k}$ be the $k^{\text {th }}$ column of $A_{k-1}$ scaled such that $L_{k, k}=1$. Set $D_{k, k}=\left(A_{k-1}\right){k, k}$ and calculate $A{k}=A_{k-1}-D_{k, k} \mathbf{l}{k} \mathbf{l}{k}^{T}$.
An example of such a factorization is
$$\left(\begin{array}{ll} 4 & 1 \ 1 & 4 \end{array}\right)=\left(\begin{array}{ll} 1 & 0 \ \frac{1}{4} & 1 \end{array}\right)\left(\begin{array}{cc} 4 & 0 \ 0 & \frac{15}{4} \end{array}\right)\left(\begin{array}{ll} 1 & \frac{1}{4} \ 0 & 1 \end{array}\right) .$$
Recall that $A$ is positive definite if $\mathbf{x}^{T} A \mathbf{x}>0$ for all $\mathbf{x} \neq 0$.

## 统计代写|数值分析和优化代写numerical analysis and optimazation代考|QR Factorization

In the following we examine another way to factorize a matrix. However, first we need to recall a few concepts.
For all $\mathbf{x}, \mathbf{y} \in \mathbb{R}^{n}$, the scalar product is defined by
$$\langle\mathbf{x}, \mathbf{y}\rangle=\langle\mathbf{y}, \mathbf{x}\rangle=\sum_{i=1}^{n} x_{i} y_{i}=\mathbf{x}^{T} \mathbf{y}=\mathbf{y}^{T} \mathbf{x}$$
The scalar product is a linear operation, i.e., for $\mathbf{x}, \mathbf{y}, \mathbf{z} \in \mathbb{R}^{n}$ and $\alpha, \beta \in \mathbb{R}$
$$\langle\alpha \mathbf{x}+\beta \mathbf{y}, \mathbf{z}\rangle=\alpha\langle\mathbf{x}, \mathbf{z}\rangle+\beta\langle\mathbf{y}, \mathbf{z}\rangle$$
The norm or Euclidean length of $\mathbf{x} \in \mathbb{R}^{n}$ is defined as
$$|\mathbf{x}|=\left(\sum_{i=1}^{n} x_{i}^{2}\right)^{1 / 2}=\langle\mathbf{x}, \mathbf{x}\rangle^{1 / 2} \geq 0$$
The norm of $\mathbf{x}$ is zero if and only if $\mathbf{x}$ is the zero vector.
Two vectors $\mathbf{x}, \mathbf{y} \in \mathbb{R}^{n}$ are called orthogonal to each other if
$$\langle\mathbf{x}, \mathbf{y}\rangle=0$$
Of course the zero vector is orthogonal to every vector including itself.
A set of vectors $\mathbf{q}{1}, \ldots, \mathbf{q}{m} \in \mathbb{R}^{n}$ is called orthonormal if
$$\left\langle\mathbf{q}{k}, \mathbf{q}{l}\right\rangle=\left{\begin{array}{ll} 1, & k=l, \ 0, & k \neq l, \end{array} \quad k, l=1, \ldots, m .\right.$$
Let $Q=\left(\begin{array}{lll}\mathbf{q}{1} & \ldots & \mathbf{q}{n}\end{array}\right)$ be an $n \times n$ real matrix. It is called orthogonal if its columns are orthonormal. It follows from $\left(Q^{T} Q\right){k, l}=\left\langle\mathbf{q}{k}, \mathbf{q}_{l}\right\rangle$ that $Q^{T} Q=I$ where $I$ is the unit or identity matrix. Thus $Q$ is nonsingular and the inverse exists, $Q^{-1}=Q^{T}$. Furthermore, $Q Q^{T}=Q Q^{-1}=I$. Therefore the rows of an orthogonal matrix are also orthonormal and $Q^{T}$ is also an orthogonal matrix. Further, $1=\operatorname{det} I=\operatorname{det}\left(Q Q^{T}\right)=\operatorname{det} Q \operatorname{det} Q^{T}=(\operatorname{det} Q)^{2}$ and we deduce $\operatorname{det} Q=\pm 1$.
Lemma 2.1. If $P, Q$ are orthogonal, then so is $P Q$.
Proof. Since $P^{T} P=Q^{T} Q=I$, we have
$$(P Q)^{T}(P Q)=\left(Q^{T} P^{T}\right)(P Q)=Q^{T}\left(P^{T} P\right) Q=Q^{T} Q=I$$
and hence $P Q$ is orthogonal.
We will require the following lemma to construct orthogonal matrices.

## 统计代写|数值分析和优化代写numerical analysis and optimazation代考|Givens Rotations

Given a real $n \times m$ matrix $A$, we let $A_{0}=A$ and seek a sequence $\Omega_{1}, \ldots, \Omega_{k}$ of $n \times n$ orthogonal matrices such that the matrix $A_{i}:=\Omega_{i} A_{i-1}$ has more zeros below the diagonal than $A_{i-1}$ for $i=1, \ldots, k$. The insertion of zeros shall be in such a way that $A_{k}$ is upper triangular. We then set $R=A_{k}$. Hence $\Omega_{k} \cdots \Omega_{1} A=R$ and $Q=\left(\Omega_{k} \cdots \Omega_{1}\right)^{-1}=\left(\Omega_{k} \cdots \Omega_{1}\right)^{T}=\Omega_{1}^{T} \cdots \Omega_{k}^{T}$. Therefore $A=Q R$ and $Q$ is orthogonal and $R$ is upper triangular.

Definition 2.4 (Givens rotation). An $n \times n$ orthogonal matrix $\Omega$ is called a Givens rotation, if it is the same as the identity matrix except for four elements and we have det $\Omega=1$. Specifically we write $\Omega^{[p, q]}$, where $1 \leq p<q \leq n$, for a matrix such that
$$\Omega_{p, p}^{[p, q]}=\Omega_{q, q}^{[p, q]}=\cos \theta, \quad \Omega_{p, q}^{[p, q]}=\sin \theta, \quad \Omega_{q, p}^{[p, q]}=-\sin \theta$$
for some $\theta \in[-\pi, \pi]$.
Letting $n=4$ we have for example
Geometrically these matrices correspond to the underlying coordinate system being rotated along a two-dimensional plane, which is called a Euler rotation in mechanics. Orthogonality is easily verified using the identity $\cos ^{2} \theta+\sin ^{2} \theta=1$.

## 统计代写|数值分析和优化代写numerical analysis and optimazation代考|Cholesky Factorization

(41 14)=(10 141)(40 0154)(114 01).

## 统计代写|数值分析和优化代写numerical analysis and optimazation代考|QR Factorization

⟨X,是⟩=⟨是,X⟩=∑一世=1nX一世是一世=X吨是=是吨X

⟨一种X+b是,和⟩=一种⟨X,和⟩+b⟨是,和⟩

|X|=(∑一世=1nX一世2)1/2=⟨X,X⟩1/2≥0

⟨X,是⟩=0

$$\left\langle\mathbf{q}{k}, \mathbf{q}{l}\right\rangle=\left{1,ķ=l, 0,ķ≠l,\quad k, l=1, \ldots, m .\right. 大号和吨问=(q1…qn)b和一种nn×nr和一种l米一种吨r一世X.一世吨一世sC一种ll和d这r吨H这G这n一种l一世F一世吨sC这l在米ns一种r和这r吨H这n这r米一种l.一世吨F这ll这在sFr这米(问吨问)ķ,l=⟨qķ,ql⟩吨H一种吨问吨问=一世在H和r和一世一世s吨H和在n一世吨这r一世d和n吨一世吨是米一种吨r一世X.吨H在s问一世sn这ns一世nG在l一种r一种nd吨H和一世n在和rs和和X一世s吨s,问−1=问吨.F在r吨H和r米这r和,问问吨=问问−1=一世.吨H和r和F这r和吨H和r这在s这F一种n这r吨H这G这n一种l米一种吨r一世X一种r和一种ls这这r吨H这n这r米一种l一种nd问吨一世s一种ls这一种n这r吨H这G这n一种l米一种吨r一世X.F在r吨H和r,1=这一世=这(问问吨)=这问这问吨=(这问)2一种nd在和d和d在C和这问=±1.大号和米米一种2.1.一世F磷,问一种r和这r吨H这G这n一种l,吨H和ns这一世s磷问.磷r这这F.小号一世nC和磷吨磷=问吨问=一世,在和H一种在和 (PQ)^{T}(PQ)=\left(Q^{T} P^{T}\right)(PQ)=Q^{T}\left(P^{T} P\right) Q= Q^{T} Q=I$$

## 统计代写|数值分析和优化代写numerical analysis and optimazation代考|Givens Rotations

Ωp,p[p,q]=Ωq,q[p,q]=因θ,Ωp,q[p,q]=罪θ,Ωq,p[p,q]=−罪θ

，在几何上，这些矩阵对应于沿二维平面旋转的基础坐标系，这在力学中称为欧拉旋转。使用身份很容易验证正交性因2θ+罪2θ=1.

## 广义线性模型代考

statistics-lab作为专业的留学生服务机构，多年来已为美国、英国、加拿大、澳洲等留学热门地的学生提供专业的学术服务，包括但不限于Essay代写，Assignment代写，Dissertation代写，Report代写，小组作业代写，Proposal代写，Paper代写，Presentation代写，计算机作业代写，论文修改和润色，网课代做，exam代考等等。写作范围涵盖高中，本科，研究生等海外留学全阶段，辐射金融，经济学，会计学，审计学，管理学等全球99%专业科目。写作团队既有专业英语母语作者，也有海外名校硕博留学生，每位写作老师都拥有过硬的语言能力，专业的学科背景和学术写作经验。我们承诺100%原创，100%专业，100%准时，100%满意。

## MATLAB代写

MATLAB 是一种用于技术计算的高性能语言。它将计算、可视化和编程集成在一个易于使用的环境中，其中问题和解决方案以熟悉的数学符号表示。典型用途包括：数学和计算算法开发建模、仿真和原型制作数据分析、探索和可视化科学和工程图形应用程序开发，包括图形用户界面构建MATLAB 是一个交互式系统，其基本数据元素是一个不需要维度的数组。这使您可以解决许多技术计算问题，尤其是那些具有矩阵和向量公式的问题，而只需用 C 或 Fortran 等标量非交互式语言编写程序所需的时间的一小部分。MATLAB 名称代表矩阵实验室。MATLAB 最初的编写目的是提供对由 LINPACK 和 EISPACK 项目开发的矩阵软件的轻松访问，这两个项目共同代表了矩阵计算软件的最新技术。MATLAB 经过多年的发展，得到了许多用户的投入。在大学环境中，它是数学、工程和科学入门和高级课程的标准教学工具。在工业领域，MATLAB 是高效研究、开发和分析的首选工具。MATLAB 具有一系列称为工具箱的特定于应用程序的解决方案。对于大多数 MATLAB 用户来说非常重要，工具箱允许您学习应用专业技术。工具箱是 MATLAB 函数（M 文件）的综合集合，可扩展 MATLAB 环境以解决特定类别的问题。可用工具箱的领域包括信号处理、控制系统、神经网络、模糊逻辑、小波、仿真等。

format: plain


text:
# Assignment 5

Assignment 5 is now available! There is no standalone document for this assignment, just a code skeleton in the class repository and section 8.1 of the class notes. You do not need to submit the exercises in the text, only the programming component. This assignment will be due at 11:00 pm on March 28th. The submission guidelines are identical to the previous assignments. Electronic submissions are preferred (cc’ing both kmcrane@cs.cmu.edu and nsharp@cs.cmu.edu).

Additionally, include in your email a paragraph or two commenting on the results of this assignment. If your implementation is successful, analyze the results and comment on why they make sense. If you do not have faith in your results, comment on what appears to be wrong and what may be the cause.

## 3 thoughts on “Assignment 5”

1. Slav says:

In section 8.1 of the notes, it mentions that system solvers ‘solvePositiveDefinite’ and ‘solveSquare” are provided that we can use. Are these indeed provided? If so, how should they be called? (they were not found when I tried to call them)

1. Khryl says:

@Slav, I’m not using these two methods. I just use scipy.sparse.linalg.spsolve to solve the problem. It’s usually pretty fast.

1. ^^^ This is the right idea! Those method names referenced in the text correspond to a previous version of this codebase, we’ll just be using the methods in scipy.sparse.

If you find yourself wanting anything else you can find a thorough list of the available routines here http://docs.scipy.org/doc/scipy/reference/sparse.linalg.html .

To call them, you’ll want to use something like scipy.sparse.linalg.spsolve(arguments).


text:
# The Time it Takes to Fill

Water is being continually poured into a container with a volume of 30 cubic meters at a constant rate. We measured the mass flow rate at 10 kilograms per second. How many seconds will it take for the water to fill up the container from when it began?

Details and Assumptions:

The mass flow rate, for this purpose, is given by this formula:

$$\dot { m } =\rho \cdot Q$$

where $$\dot { m }$$ is the mass flow rate (in $$\text{kg/s}$$), $$\rho$$ is density, and $$Q$$ is the volume flow rate (in $${ \text{m} }^{ 3 }\text{/s}$$).

Take the density of water to be 1000 kilograms per cubic meter.


text:
# zbMATH — the first resource for mathematics

Thompson’s problem ($$\sigma^2=3$$) With two appendices. I: The numerical verification of Thompson’s identity by Andrew Odlyzko: II: A check of the Ree group conjecture for small fields by David Hunt. (English) Zbl 0442.20016

##### MSC:
 20D05 Finite simple groups and their classification 11T30 Structure theory for finite fields and commutative rings (number-theoretic aspects) 20G40 Linear algebraic groups over finite fields 20B25 Finite automorphism groups of algebraic, geometric, or combinatorial structures 11T06 Polynomials over finite fields 11E57 Classical groups
Full Text:
##### References:
 [1] [T] Thompson, J.: Toward a characterization ofE 2 * (q). Part I: J. Alg.7, 406-414 (1967). Part II: J. Alg.20, 610-621 (1972 Part III: J. Alg.49, 162-166 (1977)
This reference list is based on information provided by the publisher or from digital mathematics libraries. Its items are heuristically matched to zbMATH identifiers and may contain data conversion errors. It attempts to reflect the references listed in the original paper as accurately as possible without claiming the completeness or perfect precision of the matching.


text:
About acceleration of block with respect to wedge and ground

1. Dec 30, 2011

caffe

Hi friendz I have a problem.
If a block of mass m is placed over the wedge such that there is no friction then what is the acceleration of block
1with respect to wedge
2 with respect to ground
My sir said that it is different.Is it so.

2. Jan 1, 2012

JHamm

For the first one you just need to consider the wedge as fixed. For the second one add the negative acceleration of the wedge to the block.

3. Jan 1, 2012

caffe

Here wedge is stationary.Now please tell me the acceleration of block with respect to wedge and ground.

4. Jan 1, 2012

Staff: Mentor

Please state the exact problem you are trying to solve.

5. Jan 1, 2012

caffe

My question is that there is a stationary wedge on which block is placed and all the sutfaces are smooth.Now according to mg physics teacher the acceleration of block with respect to wedge is gsin@ and with respect to ground is g .Is it true.But according to my knowledge as we read that accelaration of any body with respect to two different inertial frame is same.Now here block and ground are two different inertial frames.Then why acceleration of block with respect to wedge and ground different.

6. Jan 1, 2012

Staff: Mentor

OK, the wedge is fixed and not free to slide. But there's no friction between block and wedge.
No. The acceleration of the block with respect to both the wedge and the ground is gsinθ.
Your thinking is correct. The wedge and ground are both at rest in the same inertial frame. So the acceleration of the sliding block is the same with respect to each.

7. Jan 1, 2012

Thanks .
Sir.....


text:
# Transfinite Adams representability

Speaker:
Oriol Raventos
Thursday, July 25, 2013 - from 17:30 to 17:55
Abstract:
We consider the following problems in a well generated triangulated category $\mathscr{T}$. Let $\alpha$ be a regular cardinal and $\mathscr{T}^{\alpha}\subset \mathscr{T}$ the full subcategory of $\alpha$\nobreakdash-compact objects. Is every functor $H\colon (\mathscr{T}^{\alpha})^{\rm op}\rightarrow{\rm Ab}$ that preserves products of $<\alpha$ objects and takes exact triangles to exact sequences of the form $H\cong\mathscr{T}(-,X)_{|_{\mathscr{T}^{\alpha}}}$ for some $X$ in $\mathscr{T}$? Is every natural transformation $\tau\colon \mathscr{T}(-,X)_{|_{\mathscr{T}^{\alpha}}}\rightarrow \mathscr{T}(-,Y)_{|_{\mathscr{T}^{\alpha}}}$ of the form $\tau=\mathscr{T}(-,f)_{|_{\mathscr{T}^{\alpha}}}$ for some $f\colon X\rightarrow Y$ in $\mathscr{T}$? If the answer to both questions is positive we say that $\mathscr{T}$ satisfies $\alpha$\nobreakdash-Adams representability. A classical result going back to Brown and Adams shows that the stable homotopy category satisfies $\aleph_{0}$\nobreakdash-Adams representability. The case $\alpha=\aleph_{0}$ is well understood thanks to the work of Christensen, Keller and Neeman. We define an obstruction theory to decide when $\mathscr{T}$ satisfies $\alpha$\nobreakdash-Adams representability. We derive necessary and sufficient conditions of homological nature, and we exhibit several examples. In particular, we show that, for all $\alpha\geq\aleph_{0}$, there are rings whose derived category satisfies $\alpha$\nobreakdash-Adams representability and also rings for which the answer to the second question is~no. All the results are in joint work with Fernando Muro.
Slides:


text:
# To Dream of Magick

## Abstracting the Monad Stack, Part 1

Posted on Thu Sep 21 04:00:00 UTC 2017

As a sidenote, my previous articles were all in terms of a fictitious image processing program. I am actually very interested in image processing, but that is not the code I have on hand, so for my examples, I am switching over to a health-tracking application that I've been working on for a while. I'll probably change the previous articles to reflect it. I am making this change, though, primarily because there are so many real examples for me to draw from.

Here is the application in question, and it is under active development. I have some layer refactoring to do, but the code is stable and I am mostly focusing my efforts on additional features.

Code for this section

Fortunately for everyone, they are almost identical to application monads, but with one twist that I want to lead you to.

In my health application, I have a library that forms the "application" and that library is meant to be wrapped around interface layers, such as the web API or a GUI. The application library is basically a set of functions that make a complete API that I can execute in the REPL.

So, assume a monad like this one:

data AppContext = App { weightSeries       :: TimeSeries Weight
, timeDistanceSeries :: TimeSeries TimeDistance
, stepSeries         :: TimeSeries Steps
}

-- TODO: handle time series exceptions. Make this less absurd.
data HealthException = TimeSeriesExc SeriesExc
| UnknownException String
deriving (Eq, Show)

newtype HealthM a = HealthM (ReaderT AppContext (ExceptT HealthException IO) a)

runHealthM :: AppContext -> HealthM a -> IO (Either HealthException a)
runHealthM ctx (HealthM act) = runExceptT (runReaderT act ctx)

(yes, that is a real TODO item in the code)

On it's own, this isn't bad. But the pain lies in that this is a library, and thus will likely end up in a different monad stack. As it is written, I would need to unroll this stack into IO and then re-roll it into my web stack. This is not horrible, but it is annoying. In the health application, I would do the re-rolling to glue these functions into my Web application monad, and it would look like this:

data Config = Config
data WebContext = WebContext { config :: Config, app :: AppContext }

newtype WebM a = WebM (ReaderT WebContext (ExceptT WebExc IO) a)

handleSaveTimeDistance :: Maybe SampleID -> SetTimeDistanceParameters -> WebM (Sample TimeDistance)
handleSaveTimeDistance sampleId params =
let workoutFromParams = undefined
workout = workoutFromParams params
in do
res <- liftIO $runHealthM app$ saveTimeDistance sampleId workout
case res of
Left err -> throwError $AppExc err Right val -> return val saveTimeDistance :: Maybe SampleID -> TimeDistance -> HealthM (Sample TimeDistance) Again, this is not awful, but it is tedious. It can also become awful if I want to perform multiple operations from the library interleaved with operations from my webapp. For example, what if I want to query every series that I am storing? handleGetHistory :: Interval UTCTime -> WebM ([Sample Weight], [Sample TimeDistance], [Sample Steps]) handleGetHistory interval = do WebContext{..} <- ask weightRes <- liftIO$ runHealthM app $getWeights interval timeDistanceRes <- liftIO$ runHealthM app $getTimeDistance interval stepRes <- liftIO$ runHealthM app $getSteps interval case (weightRes, timeDistanceRes, stepRes) of (Left err, _, _) -> throwError$ AppExc err
(_, Left err, _) -> throwError $AppExc err (_, _, Left err) -> throwError$ AppExc err
(Right weights, Right timeDistances, Right steps) -> pure (weights, timeDistances, steps)

getWeights :: Interval UTCTime -> HealthM [Sample Weight]
getTimeDistance :: Interval UTCTime -> HealthM [Sample TimeDistance]
getSteps :: Interval UTCTime -> HealthM [Sample Steps]

### Rewrapping the context

Code for this section

The first, most obvious solution, is a helper function to re-wrap:

wrapEitherIO :: (exc -> WebExc) -> IO (Either exc a) -> WebM a
wrapEitherIO excTr act =
liftIO act >>= either (throwError . excTr) pure

handleGetHistory :: Interval UTCTime -> WebM ([Sample Weight], [Sample TimeDistance], [Sample Steps])
handleGetHistory interval = do
weights <- wrapEitherIO AppExc $runHealthM app$ getWeights interval
timeDistances <- wrapEitherIO AppExc $runHealthM app$ getTimeDistance interval
steps <- wrapEitherIO AppExc $runHealthM app$ getSteps interval
pure (weights, timeDistances, steps)

And then, probably even one step further with a utility function to do the re-wrapping.

wrapEitherIO :: (exc -> WebExc) -> IO (Either exc a) -> WebM a
wrapEitherIO excTr act =
liftIO act >>= either (throwError . excTr) pure

runHealthMInWebM :: (HealthException -> WebExc) -> AppContext -> HealthM a -> WebM a
runHealthMInWebM handler app = wrapEitherIO handler . runHealthM app

handleGetHistory :: Interval UTCTime -> WebM ([Sample Weight], [Sample TimeDistance], [Sample Steps])
handleGetHistory interval = do
weights <- runHealthMInWebM AppExc app $getWeights interval timeDistances <- runHealthMInWebM AppExc app$ getTimeDistance interval
steps <- runHealthMInWebM AppExc app $getSteps interval pure (weights, timeDistances, steps) This alone makes life much nicer. All of the exception checking boilerplate gets encapsulated into wrapEitherIO, and so every step of handleGetHistory gets to exist on the happy path. In many instances, I could just call this done. Servant actually provides a typeclass for natural transformations which abstracts this away. It has a challenging type signature, but it is pretty nice and I recommend taking a look at it. ### Type Constraints Code for this section I use type constraints as my preferred method for solving this problem. The idea behind it is that I try to have only one concrete monad stack anywhere in the application. A "type constraint" is a mechanism by which I declare that a context must implement a particular typeclass, but that the context could be any context that implements that typeclass. A trivial example would be like this: printSomeStuff :: (Show a, MonadIO m) => a -> m () printSomeStuff a = do liftIO$ putStrLn $show a This function will print out any value, so long as the value implements Show and so long as the function is called in any monad that implements MonadIO. For instance, all three of these calls to printSomeStuff are valid: run1 :: IO () run1 = printSomeStuff "abcd" run2 :: ExceptT String IO () run2 = printSomeStuff "abcd" run3 :: MonadIO m => m () run3 = printSomeStuff "abcd" Now, we build up on this concept, and to do so I'm going to repack all three of my get functions, this time starting from the simplest possible implementation. saveTimeDistance :: Maybe SampleID -> TimeDistance -> AppContext -> IO (Either HealthException a) handleSaveTimeDistance :: Maybe SampleID -> SetTimeDistanceParameters -> WebM (Sample TimeDistance) handleSaveTimeDistance sampleId params = let workoutFromParams = undefined workout = workoutFromParams params in do WebContext{..} <- ask res <- liftIO$ saveTimeDistance sampleId workout app
case res of
Left err -> throwError $AppExc err Right val -> pure val saveTimeDistance can function in any monad that implements MonadIO, so the first thing I will do is to abstract that away: saveTimeDistance :: (MonadIO m) => Maybe SampleId -> TimeDistance -> AppContext -> m (Either HealthException a) handleSaveTimeDistance :: Maybe SampleID -> SetTimeDistanceParameters -> WebM (Sample TimeDistance) handleSaveTimeDistance sampleId params = let workoutFromParams = undefined workout = workoutFromParams params in do WebContext{..} <- ask res <- saveTimeDistance sampleId workout app case res of Left err -> throwError$ AppExc err
Right val -> pure val

This detaches me from a particular monad stack. This function can now be called as-is from any context that implements, hence in the above code, I no longer need to apply liftIO to saveTimeDistance. For bookkeeping, and because I am going to build upon this abstraction, I will give that type constraint a name:

type HealthM m = MonadIO m

saveTimeDistance :: HealthM m => Maybe SampleID -> TimeDistance -> AppContext -> m (Either HealthException a)

The next step requires a fairly large jump. I want to eliminate that AppContext parameter. It is required for every function in the health application, so it would be nice if I could pass it as part of a MonadReader. The naive solution would be to just do this:

type HealthM m = (MonadIO m, MonadReader AppContext m)

saveTimeDistance :: HealthM m => Maybe SampleID -> TimeDistance -> m (Either HealthException a)

Unfortunately, this actually is of detriment in the caller. If the caller has its own context in a MonadReader, that context is not likely to be the same as this one. The result is code that looks like this:

handleSaveTimeDistance :: Maybe SampleID -> SetTimeDistanceParameters -> WebM (Sample TimeDistance)
handleSaveTimeDistance sampleId params =
let workoutFromParams = undefined
workout = workoutFromParams params
in do
res <- runReaderT (saveTimeDistance sampleId workout) app
case res of
Left err -> throwError $AppExc err Right val -> pure val I definitely do not want to be going in the direction of having to re-add a run function stack, but that is how this goes. The caller has to explicitely pull out the context for this call. In order to get around this, I have to think a bit differently. I still want an implicit context of AppContext. But, really, the context could be larger so long as AppContext is present in it. So an alternate solution looks like this: type HealthM r m = (MonadIO m, MonadReader WebContext m) saveTimeDistance :: Health r m => Maybe SampleID -> TimeDistance -> m (Either HealthException a) saveTimeDistance = undefined handleSaveTimeDistance :: Maybe SampleID -> SetTimeDistanceParameters -> WebM (Sample TimeDistance) handleSaveTimeDistance sampleId params = let workoutFromParams = undefined workout = workoutFromParams params in do res <- saveTimeDistance sampleId workout case res of Left err -> throwError$ AppExc err
Right val -> pure val

In some ways, this looks better. The caller now can simply treat saveTimeDistance as part of WebM. But now saveTimeDistance becomes aware of WebContext, and so is beholden to a single caller. This is better, but not good enough.

What I want is a way to specify that saveTimeDistance can take any context, so long as that context provides me with a way to extract the AppContext. So, this is a constraint upon a constraint, and it ends up looking like this:

type HealthM = (MonadIO m, MonadReader r m, HasHealthContext r)

Basically, a HealthM function can take any MonadReader that provides r, so long as r "has a health context".

My library gets to declare the HasHealthContext interface. The caller needs to implement that interface for its own context.

type Health r m = (MonadIO m, MonadReader r m, HasHealthContext r)
class HasHealthContext ctx where
hasAppContext :: ctx -> AppContext

WebContext = WebContext { config :: Config, app :: AppContext }
instance HasHealthContext WebContext where
hasAppContext WebContext{..} = app

saveTimeDistance :: Health r m => Maybe SampleID -> TimeDistance -> m (Either HealthException a)
saveTimeDistance _ _ = do
appCtx <- hasAppContext <$> ask ... With similar improvements made to getWeights, getTimeDistance, and getSteps, handleGetHistory also gets much nicer, and that demonstrates exactly what we wanted to begin with: handleGetHistory :: Interval UTCTime -> WebM ([Sample Weight], [Sample TimeDistance], [Sample Steps]) handleGetHistory interval = do WebContext{..} <- ask weightRes <- getWeights interval timeDistanceRes <- getTimeDistance interval stepRes <- getSteps interval case (weightRes, timeDistanceRes, stepRes) of (Left err, _, _) -> throwError$ AppExc err
(_, Left err, _) -> throwError $AppExc err (_, _, Left err) -> throwError$ AppExc err
(Right weights, Right timeDistances, Right steps) -> pure (weights, timeDistances, steps)

getWeights :: Health r m => Interval UTCTime -> m (Either HealthException a)
getWeights = undefined

getTimeDistance :: Health r m => Interval UTCTime -> m (Either HealthException a)
getTimeDistance = undefined

getSteps :: Health r m => Interval UTCTime -> m (Either HealthException a)
getSteps = undefined

### Looking forward

Not quite there yet. We still have some tedium with exception handling to do. In this system, any thrown SeriesExc must be caught and then re-wrapped in the HealthException in order for the application to typecheck and for the exception to propogate upwards. This sort of tedium likely drove the creation of extensible IO exceptions, which I view as unchecked and undocumented parts of the type signature.

So, the next step will be to abstraction the exception throwing mechanism. Look for that in coming weeks.

## A Nazi Sympathizer in the White House

Posted on Wed Aug 16 16:00:00 UTC 2017

The President of the United States is a Nazi sympathizer and a white supremacist. He is a traitor to the nation.

The Republican party wants to pretend that they didn't know this. But Clinton warned us a year ago. He won anyway. 62 million people wanted a white supremacist rather than a woman.

I am but one white, trans, queer, able-bodied, priveleged voice howling in the wind. Far smarter people than me know precisely how we got to this point. Far smarter people than me know that we never really left this point.

So here are real, concrete actions that will push back this tide.

Listen to black people. Listen to queer people. They never stopped tell us how bad things are.

Black Lives Matter.

Posted on Fri Jul 14 16:00:00 UTC 2017

We want to get productive in Haskell very quickly. Most non-trivial applications will have configuration, connections to the outside world, can hit exceptional conditions, and benefit from having their operations logged. If your application has sensible logs at both high an low levels of detail, your devops team will thank you and your life of debugging a production application will be a happier one.

I want to get all of these things at once, and so it would be nice to provide a nearly boilerplate application stack that provides them all. I define the "application stack" as a group of attributes that contain the context and all of the common behaviors for an application. In Haskell, you do that with a monad stack, though work on extensible effects shows a great deal of promise and has been used to great effect in Purescript.

That said, I use monads and monad transformers, and I'll not explain either of them today. I feel that the best explanation is a non-trivial example implementation, which I will do in a future article, or refer you to a better tutorial.

While most of this article explains the process, the final result is this application stack, which may be all you need if you are already familiar with building monad transformer stacks.

data Context = Context { contextRoot :: FilePath } deriving Show

data AppError = AppError deriving Show

newtype AppM a = AppM (LoggingT (ReaderT Context (ExceptT AppError IO)) a)

runAppM :: Context -> AppM a -> IO (Either AppError a)
runAppM ctx (AppM act) = runExceptT (runReaderT (runStderrLoggingT act) ctx)

### The most basic stack

Almost every application needs IO. In Haskell it is difficult to do IO on top of anything (see MonadBaseControl for way), so I always put it at the bottom of the monad stack. A trivial application stack would look like this:

newtype AppM a = AppM (IO a) deriving (Functor, Applicative, Monad, MonadIO)

This is so trivial you will likely never do it, though it can be helpful in that it prevents confusion between your functions and system IO functions. Still, let's build out what you need to make this work.

First of all, you do want AppM to be a monad, and you will need MonadIO in order to actually run IO operations. The primary use that I have for Monads in an application is to eliminate the boilerplate involved with a lot of threading context through a series of function calls. More to the point, though, you cannot get MonadExcept, MonadReader, or MonadLogger into this stack without having Monad to begin with.

newtype AppM a = AppM (IO a)

runAppM :: AppM a -> IO a
runAppM (AppM act) = act

runAppM is the function that connects your application stack to the Haskell IO stack. This is everything you need in order to create a stack: the stack itself and the runner. Now let's see it in action:

data Image = Image deriving Show

loadImage :: FilePath -> AppM Image
liftIO $putStrLn$ "loadImage: " <> path
pure Image

main :: IO ()
main = do

main :: IO ()
main = do
res <- runAppM ctx $do img1 <- loadImage "image.png" img2 <- loadImage "image2.png" pure (img1, img2) print res Suddenly, everything in Context is available to every function that runs in AppM. You get the local effect of global parameters while still getting to isolate them, potentially calling the same functions with different contexts within the same application. ### Add exception handling and logging Exceptions happen. The Haskell community is split between what I call explicit vs. implicit exceptions. In short, implicit exceptions are not declared in the type signature, can happen from any function, and can only be caught in IO code. Explicit exceptions are explicitely stated in the type signature and can be caught just about anywhere. I prefer them for all of my application errors. I'll give exception handling further treatment in a future article, and will show the use of explicit exceptions here. Logging is almost always helpful for any application that is not of trivial size. And, once present, it can replace print for debugging, allowing debugging lines to remain present in the code for those cases when something starts going wrong in production. First, the new application stack: data AppError = AppError deriving Show newtype AppM a = AppM (LoggingT (ReaderT Context (ExceptT AppError IO)) a) deriving ( Functor, Applicative, Monad, MonadIO , MonadError AppError, MonadReader Context, MonadLogger) runAppM :: Context -> AppM a -> IO (Either AppError a) runAppM ctx (AppM act) = runExceptT (runReaderT (runStderrLoggingT act) ctx) This gets quite a bit more complicated with both the Logging and Exceptions being added. Remember that I use the term "stack" here, and each monad transformer involved represents another layer in the stack. When running the stack, you must peel off each layer in reverse order. I will illustrate with some types: *Json> :t loadImage "img.png" loadImage "img.png" :: AppM Image *Json> :t unAppM$ loadImage "img.png"
unAppM $loadImage "img.png" :: LoggingT (ReaderT Context (ExceptT AppError IO)) Image *Json> :t runStderrLoggingT$ unAppM $loadImage "img.png" runStderrLoggingT$ unAppM $loadImage "img.png" :: ReaderT Context (ExceptT AppError IO) Image *Json> :t runReaderT (runStderrLoggingT$ unAppM $loadImage "img.png") ctx runReaderT (runStderrLoggingT$ unAppM $loadImage "img.png") ctx :: ExceptT AppError IO Image *Json> :t runExceptT$ runReaderT (runStderrLoggingT $unAppM$ loadImage "img.png") ctx
runExceptT $runReaderT (runStderrLoggingT$ unAppM $loadImage "img.png") ctx :: IO (Either AppError Image) The point of this is that in runAppM, the type of act is the entire stack, and the first thing to be called to begin unwrapping is runStderrLoggingT, then runReaderT, and finally runExceptT. Notice, also, that the final type of runAppM has changed to IO (Either AppError a). runAppM will now return whatever exception gets thrown from within the context it is running, no matter where that exception is thrown, if that exception is thrown with throwException. Exceptions thrown with throw end up being the implicit exceptions I referred to, and those require some extra handling. So, here is the rest of the code. In the places where I used to print output, I am now logging output. Note that the loggers require TemplateHaskell and have slightly odd syntax, but are otherwise nearly identical to print. data Image = Image deriving Show loadImage :: FilePath -> AppM Image loadImage path = do Context{..} <- ask$(logInfo) (T.pack $"loadImage: " <> (contextRoot </> path)) pure Image loadContext :: IO Context loadContext = pure$ Context { contextRoot = "/home/savanni/Pictures/" }

main :: IO ()
main = do
do  res <- runAppM ctx $do img1 <- loadImage "image.png" img2 <- loadImage "image2.png" pure (img1, img2) print res do res <- runAppM ctx$ do
throwError AppError
pure (img1, img2)
print res

This is the output from running main:

*Json> main
Right (Image,Image)
Left AppError
*Json>

So, the first block starting with do res <- runAppM runs to completion, returnin two images. The second block, runs loadImage for the first image, but then hits throwError and returns Left AppError, discarding the first image and not loading the second image at all.

This is nearly a application stack that I have used for more applications than I can count. Even if you need only one feature, such as exceptions, starting with a small stack hidden behind an application monad makes it very easy to add additional features as you need them, without needing to change the rest of your code. This pattern is trivial to extend, or contract, as needed, and so I think it starts every application on a good path.

## Reflections

Posted on Mon Jul 10 12:00:00 UTC 2017

I left CollegeVine a little over two weeks ago. Since then, I have gotten myself really busy. For a moment tonight I am going to slow down to reflect on my time since leaving.

First of all, I had an obligatory Friday of just not doing anything. But by Saturday, I got to work. In the last two weeks I have...

• 86 commits to 4 repositories
• representing a new library that puts some workflow around JWTs for capability or token based authentication
• extracting an existing module into its own library
• converting the authentication scheme of two applications to use the capability tokens
• build out a Javascript, React, Redux frontend for my health application, comprising of the bulk of my time, and 1000 lines of code
• multiple interviews with three different companies and a starter interview with a fourth
• laziness and playing during the 4th of July
• I got engaged!!!

Quite the mouthful!

I moved to Boston to be close to my partners, Cait and Leah. For the last year we have all danced around and away from the topic of marriage.

Finally, though, I decided I was ready, and so on the 3rd of July I asked the two of them to marry me. They both said yes.

Obviously we shall have no legal recognition. I don't even have much expectation of religious recognition. The only thing we will be asking for is that the community around us recognize our relationship, support us, and hold us accountable to the vows that we will make.

We will announce the date when we figure it out, but we may not even begin discussing the date until late this year.

### Coding without restriction

This is rather a misnomer. I start putting restrictions on my code before I even start typing the first line. I have certain habits and discipline that come from all my years of coding. Some of those habits lead me to immediately start trying to constrain the scope of what I'm writing.

But, in fact, almost everything I worked on over the last few weeks had pre-existing code that I had to work with.

At the same time, I had incredible velocity, primarily because I understood the systems I worked in. I have a history with those systems, having grown some of them since inception. I also have at least a modicum of automated tests on everything except for my APIs. Most importantly, though, since I understand the system I have no fear of breaking unrelated components. I can make changes and deliberately break things, because I either know the code or I have written automated tests that will help me detect flaws.

Obviously, when I start my next job, I need to use absolutely every tool at my disposal to learn the next system I walk into as quickly as possible. No slow "do some projects and learn by osmosis".

• map every data structure I can find and understand
• find every API endpoint
• build automated tests as soon as I find untested corners
• pair with other people on their code
• have people pair with me on my tasks
• document anything that feels undocumented

### Learning

When I am stressed, when I feel most pressured to get something done, I can't learn. Anything I learn must be in direct service of immediate needs, preferably to the point that I can simply copy-and-paste a new idea in and tweak it a bit to make it fit. This meant that I did not want to take the time to learn anything because I really needed to get the code working and the feature shipped.

When I relax, and have a project in mind, and a bit of extra time, I can learn a lot and move very quickly in my work. I barely knew any Javascript or React, and I knew no Redux, when I started. Yet I shocked a Javascript expert I know when she saw just how far and how quickly I could move.

This should have been obvious. It wasn't. Now I know.

Make no mistake, I love Haskell. But I do not necessarily love the Haskell community. I have met some decent people there, but I have also seen bro-level toxicity. I think that Haskell has a lot of elitism around it, and that attracts the kind of human beings I most dislike. As such, since CollegeVine was probably the least toxic Haskell environment I have encountered, I will not seek another Haskell job until I can create it out of a team of junior programmers who are really excited to learn new things.

### Moving forward

I am pretty sure that I am done with interviews with one company. I have additional interviews with two others and think that the fourth will not turn into anything. Some of the positions are really compelling. So, I have an exciting future coming up, and I hope to actually have a new employement contract signed before I have been out of work for a full month.

We shall see. But the future looks bright.

Posted on Mon Jun 26 19:30:00 UTC 2017

One way or another, you are going to need to configure your Haskell application, and for that you have three major ways of doing it. I recommend choosing one and sticking to it. You can choose multiple ones, but it is important that you minimize one of them in order to keep yourself out of the mind-numbing tedium of consistently combining multiple input parameter sets and their overrides.

• CLI Option parsing

I recommend this for small utilities, especially those which you are going to run frequently and with a variety of configurations.

• Configuration files

This is generally my preferred way of running an application. You'll still need to do a little bit with option parsing, but only enough to get a configuration. However, it can be a total pain to need to edit a file to change the configuration for a utlity, so use this for your longer-running applications.

• Environment variables

This is not generally how I want to configure an application, but some environments, such as Heroku, make it the easiest way.

### CLI Option Parsing

The most important rule of parsing options from the CLI is...

*Don't write your own CLI parsing library.*

I have made this mistake. It is no longer on the internet. Do not do what I have done. Do this instead.

For particularly simple parameter parsing, you don't need any libraries. For example I have a tool that I use on occasion to reformat an m3u playlist for my phone. Rhythmbox exports the playlist in an m3u format, but with all paths that don't work for my Android phone. A tool like this is so simple that the only parameters to it are the input file and the output file.

In fact, the tool is so simple that it may have been better for me to accept the input data on standard in and emit the output data on standard out. Please forgive me for that, too.
import           System.Environment (getArgs)

main :: IO ()
main = do
(source:dest:_) <- getArgs

That is the simplest way. However, you may wish to be kind to your users...

main :: IO ()
main = do
args <- getArgs
case args of
(source:dest:_) -> {- do your thing! -}
_ -> print "Run the application with the source and destination files."

This is your standby for applications with very simple parameters, and these applications are quite common. However, more complex configuration is often needed. For that, resort to Optparse-Applicative. This will give you command line options that are very similar in power to the one available in Go.

The tutorial covers basically everything, but here's a starter example:

cliParser :: Parser Config
cliParser = Config <> option auto (long "interval" <> help "number of seconds between samples" <> value 5) <*> strOption (long "log" <> help "log output file") ... main = do Config{..} <- execParser (info (helper <*> cliParser) (fullDesc <> progDesc "description of the program")) Look here for a summary of the functions and typeclasses involved above. The entire block around execParser is basically boilerplate code, and all of the interesting bits happen inside cliParser. This technique is as common as mud. As an administrator, I do like to pass parameters to my applications, but I dislike services that require excessively long command lines to run. If your application requires more than four or five parameters, or if the parameters rarely change from one run to the next, look to the next section for configuration files, instead. ### Configuration Files For almost all of my configuration needs, I like to go with a file on the disk. I usually put it into a Yaml format, because that allows some complex nested configurations and saves me from needing to write a configuration parser myself. For my example, I will demonstrate with a program that I use for my HDR processing toolchain. The program has to go through several steps, and basically it needs these parameters: • Do I need to align the photographs? • What are my input files? • What white balance parameters should I use for developing the files? and so forth. These are the most important parameters. A typical file looks like this: wb: camera project: lake-travis-dam sources: - _DSC3656.dng - _DSC3657.dng - _DSC3658.dng - _DSC3659.dng - _DSC3660.dng align: false fanout: false So, first I want a data structure to store this: data WhiteBalance = Camera | Auto data Project = Project { sources :: [String] , project :: String , wb :: WhiteBalance , align :: Bool , fanout :: Bool } deriving (Show) instance Default Project where def = Project [] "" Camera False False (incidentally, I like having defaults for my structures, if I can concieve of a reasonable default) Whether Yaml or JSON, in Haskell I need a FromJSON instance for parsing this file: instance FromJSON Project where parseJSON (Object obj) = Project <> obj .: "sources"
<*> obj .: "project"
<*> obj .: "wb"
<*> obj .: "align"
<*> obj .: "fanout"
parseJSON obj = fail $show obj instance FromJSON WhiteBalance where parseJSON (String str) = case str of "camera" -> pure Camera "auto" -> pure Auto _ -> fail$ "invalid wb string: " ++ T.unpack str
parseJSON (Object obj) =
WhiteBalance <$> obj .: "temp" <*> obj .: "green" parseJSON obj = fail$ show obj

aside: I use fail instead of mzero or mempty because propogating out any error message at all helps immensely with debugging. I wish I could use throwError, but MonadError is not implemented for Parser.

-- now include code for reading JSON format and Yaml format

### Environment Variables

While I do not particularly like using environment variables for configuration an application, Heroku and presumably some other services require their use. On the other hand, most languages treat environment variables as a simple dictionary, making them simple to retrieve. Haskell is no exception to this. The only catch is that nested structures require a little more effort to build.

Your workhorse function is System.Environment.getEnv :: String -> IO String. The function will return the value if present, or throw an IO exception if it is not present. Since you may sometimes want to make the variable optional, so, here is a function that will capture isDoesNotExistError and translate it into a Maybe:

maybeGetEnv :: String -> IO (Maybe String)
maybeGetEnv k = (Just <$> getEnv k) catch handleIOExc where handleIOExc exc | isDoesNotExistError exc = pure Nothing | otherwise = throw exc Then write your configuration function like so: import Data.List.Split (splitOn) loadConfiguration :: IO Config loadConfiguration = do p <- getEnv "PROJECT_NAME" s <- splitOn "," <$> getEnv "SOURCES"
align <- maybe False read <$> maybeEnv "ALIGN_IMAGES" fanout <- maybe False read <$> maybeEnv "FANOUT_EXPOSURES"
pure Config s p Camera align fanout These are your three major methods for configuring an application. Many applications will permit a certain degree of hybridization between them, but I think it is best to minimize that as much as possible. For instance, a command line parameter to specify the path to a configuration file. Doing it in the general case, handling command line parameters, defaults, configuration options, and environment variables, has typically lead to a very difficult-to-use mess, and I have regretted such attempts. Whichever method you use for passing configuration in, you'll then want to wrap that configuration up into a context for your application. I will hint more on that in my next article, on the application monad, and give it significantly more detailed treatment later on. Questions? Comments? Feedback? Email me. I am particularly interested in places that you feel are unclear or which could use better explanation, or experiments you have run that turned out better. ## Haskell in Production Posted on Mon Jun 26 19:00:00 UTC 2017 ### Synthesizing some hard lessons Anyone who knows me knows that I love Haskell as a programming language. I have used it professionally in several different projects, and I have used it casually in a huge number of projects. While most of my projects have never seen the light of day, several of them have made it that far at varying degrees of quality. Production code in Haskell is rare. There are lots of experiments, proofs of concept, and academic researches out there, but very few complete applications that we get to see. So there are very few instances that we get to see a successful application, much less get an explanation of how it works. Since Haskell is so strict in its effect management, it can be very difficult and tricky to assemble an application that can do what what all of your Python/C/Java/Ruby languages have instantly. This by itself makes Haskell much less likeable. You get the benefits of strict type checking and effect management, but then it becomes difficult to make different effects systems work together, and it becomes difficult to build a non-painful effects system. Over the last six months, I have finally come to understand a group of patterns that serve very well in production code. These are patterns that I would reach for instantly any time I start a new application or library. As quickly as possible I want to get to the core of my code, so it would be helpful to have an operational framework in place from the beginning that I will not later regret having. What will follow is a series of articles discussing patterns to use in setting up new Haskell applications and libraries. At all times I will welcome questions and feedback so I can make the articles better or add supplementary articles to explain sections that I may gloss over in the first pass. This series is not for advanced users or type theorists. This is for relentlessly pragmatic users who feel that Haskell is a great tool but really need to get things done very quickly without stumbling on every little nook and cranny of the language as they go. ### Older Articles ## Purescript and Haskell builds in Nix Posted on Tue Feb 7 13:00:00 UTC 2017 Stack and purescirpt do not play together particularly nicely. However, a Haskell developer working on Nix needs to be able to make them play together. There are a couple of major issues to work around. One of them is a ghc bug which you need to appease regarding library paths. I don't fully understand the library path bug, but in some way or another, it appears that GHC does not honor a particular parameter, which Nix uses to notify GHC of the active library path. However, GHC does honor LD_LIBRARY_PATH. Nix provides a way, pkgs.stdenv.lib.makeLibraryPath to convert a list of build inputs into a library path specific to that build.  LD_LIBRARY_PATH = pkgs.stdenv.lib.makeLibraryPath (buildInputs); (the parenthesis around buildInputs may be optional... I'm not really good with Nix syntax yet.) Additionally, Stack and Cabal (and, I think, Node) depend on the user's home directory, but nix package builds happen in a homeless user, and so the cache directory that all three systems depend on doesn't work. However, it turns out you can solve that simply by setting the HOME environment variable before building. { env, pkgs, ghc }: let pname = "purescript"; pversion = "0.10.3"; url = "https://github.com/purescript/purescript/archive/v{pversion}.tar.gz";
sha256 = "46c3f695ccc6e7be3cb2afe1ea9586eafdf51a04f1d40fe7240def0d8693ca68";

in env.mkDerivation rec {
name = pname;
version = pversion;

src = pkgs.fetchurl {
url = url;
sha256 = sha256;
name = pname;
};

buildInputs = [ pkgs.stack
pkgs.haskell.compiler."${ghc}" pkgs.ncurses5 pkgs.zlib pkgs.haskell.packages."${ghc}".alex
pkgs.haskell.packages."${ghc}".happy ]; # copied from generic-stack-builder.nix in the nixpkgs repository # workaround for https://ghc.haskell.org/trac/ghc/ticket/11042 LD_LIBRARY_PATH = pkgs.stdenv.lib.makeLibraryPath (buildInputs); buildCommand = '' export HOME=/tmp/stack tar -xf$src
cd purescript-0.10.3
mkdir -p $out stack build --system-ghc --local-bin-path=$out/bin --copy-bins --allow-different-user
'';
}

## Resistance

Posted on Wed Jan 18 03:30:00 UTC 2017

For the next ten days, my resistance against fascism is to sit with an enby who has just undergone surgery. The kind of person and surgery that self-proclaimed "decent folk" believe is an abomination worthy of death.

If you are one of them, fuck off.

### A Quiet Walk, Interrupted

Yesterday, my friend and I were out walking along the Delaware Canal Towpath in Morissville, Pennsylvania, having a lovely day. Part of the canal is still frozen, and we made a hobby of seeing if we could break the ice using whatever rocks we had to hand. The sound of an ice sheet fracturing is really unique. Not precisely like glass shattering, because the fracture and stresses race down the ice sheet, even if the break only happens in a small area. I lost count of the number of significant rocks that I hurled into the ice that simply got embedded.

We are pretty much minding our own business when an old man walking the other direction starts demanding to know where we're going "dressed like that" and telling us "you're not real girls". He proceeded to hurl invectives after us for long after we could hear him. He even proclaimed just how great it must be to have wealthy parents who will support my "lifestyle".

When I was twenty, I clawed my way nearly to financial independence to be free of my parents rules. I've been on my own ever since. I wanted so much to walk up and tell him precisely how much I get paid for my skills at a job that keeps me in air conditioning. The idea of shaming him into silence was almost overpowering. I am a professional in my field, not even 40, nearly at the top, and I make more money than he likely ever has.

How pathetic. Long after we could no longer hear him, we could see him still yelling at us. He had nothing better to do with his sorry excuse for a life.

It is very difficult to walk away silently. I cannot help but feel that I accomplished nothing. That there is no victory to the high road. But that perhaps there is nothing to be accomplished in my reply.

I so rarely face actual transphobia on the streets. So rarely that I vacillate between being shocked when it happens, and shocked that nobody even looks sidelong at me, even when I'm in a small town. For the rest of our walk, we kept our eyes out. We have no idea what the old man may have done. Perhaps he called the cops on us, as has happened so often to people like us. If he did, they ignored him and we continued the rest of our day unmolested.

### Decent Folk

So often, the narrative is that we are a threat to "Decent Folk". Somehow, trans queer reality is so powerful that all wholesome goodness breaks down around us.

Decent Folk assault people on the street.

Decent Folk poke their noses into other people's private lives.

Decent Folk remain silent when death camps rise.

Decent Folk vote for a fascist, rapist, traitor because he pedals lies of prosperity.

Decent Folk vote for one who promises more power to those with power.

Decent Folk are so easily duped with fascist lies.

### Defiance

What is the queer agenda? STOP HURTING OUR FRIENDS! STOP HURTING OUR CHILDREN! LET US LIVE HEALTHY PRODUCTIVE LIVES IN PEACE!

We are the ones who take in those not our kin. Teenagers thrown out of their homes for being gay, lesbian, transgender, bisexual, asexual, intersex, polyamorous. Strangers moving into a city where they can be safer.

If we could, we would walk away from your fucking "decent" culture. We would separate ourselves and build a civilization of our own. We would interact with you only to rescue the queers who emerge amongst you.

But you won't permit that. You "Decent Folk" have all the power. So fuck you.

## 16 Years

Posted on Sun Jan 1 05:00:00 UTC 2017

Welcome to 2017!

In a few days I move away from Austin, likely never to return. I grew up in Round Rock. I went away for a few years, and then I returned here to begin my career and my adult life right during the dot-com crash. I'm actually a lot older than I look. Many people upon meeting me seem to assume that I'm 27 or so, when in fact I turned 38 late this year. "Wait, how old are you?"

I keenly feel the passage of time. I feel that I have not begun to approach what I wanted to accomplish by now. But, realistically, I have between 40 and 60 years left. The amount of time that I spent here... three more times. And a lot can change in 16 years.

16 years ago, I thought I was a straight man. I was married. I voted for Bush and thought the Republicans could run the country well. I was Catholic and believed the anti-abortion rhetoric, yet I somehow rejected the anti-gay rhetoric. Go figure. Though we knew a few gay men in college, it was shortly after we moved to Austin that my wife and I noticed for the first time pairs of men openly holding hands at formal "respectable" events. We began to feel a relief that this was the kind of safe city that we never really recognized we sought.

15 years ago, my wife and I decided to have a polyamorous relationship. She said that I had suggested it years earlier while we were dating. I did not remember saying that, but it felt like the kind of thing I might have. It was shortly after this, as I thought about love, romance, and relationships, that I began to believe that it was tragic that I was straight and not bisexual. I can remember being apologetic as I (very occasionally) turned a man down. And it was shortly after this that I understood that I was parting ways with the Catholic church... and I did not particularly regret that.

14 years ago, I found out how infidelity felt. Infidelity in a polyamorous relationship looks different than in a monogamous relationship, but it hurts the same. It cuts through hearts, rips out rugs, and crushes dreams.

I also learned that maybe the Republican party was actually made up of a bunch of chronic liars, and became a Democrat. Later I started to understand how violent and hateful Republicans could be. How did I never see this before? And maybe, just maybe, I shouldn't hold the reproductive health doctrines of men who want to ban abortion but also ban all other forms of contraception and all forms of sex that carry no chance of pregnancy while simultaneously starting a war and lying to me about weapons of mass destruction!

12 years ago I joined a company that became my career for the better part of a decade. They weren't great... in fact sometimes they were downright awful, but over time my authority became vast, as did my knowledge of everything about the business... except what was in the best interest of the business. Ya know, sometimes we techies need to be informed of the big business direction so we can make decisions intelligently.

10 years ago, with the onset of Saturn Returns, I finally figured out that I was not a man. That moment has lead me through so many changes and to so many of the people that I find so important in my life now. As a man, I would never have made any of the connections I have as an androgyne. This realization sometimes keeps me awake at night, knowing that it is by the grace of but a few words that I have in my life the love that I experience now. More rationally, a few of my current friends would have been my friends anyway, and they would have noticed my egg tendencies, and they would have aided in my hatching. I may have ended up exactly where I am now, on a different schedule.

Letting go of my own gender also let me release my expectations about my sexual orientation. Reparative therapy, especially religious-based "therapy", is bullshit. We know this. And yet, I successfully "prayed the straight away"!

I also gave up on "til death do we part" and let my marriage end.

Five years ago, I learned photography, and I changed how I see the world. Always watching for that perfect moment. Seeing textures. Analyzing light. Understanding focus and freezing motion. The speckled shadow beneath a canopy. The shimmer of a cobweb five meters up and at least that far away.

Three years ago, I talked myself out of my first suicide attempt. In the aftermath, I evaluated my life. I saw clearly how I was wasting it on my employer's amazingly small dreams, and I chose to spend some time quite alone. I loved living out in the woods. I hated having to drive for twenty minutes to reach the closest decent internet connection, and for an hour to reach any of my friends. But there is a lot to be said for the peace of the forest, for stars so bright as to light the ground, for rain on the metal roof a mere meter from my lofted bed... and for really cheap rent paid in cash under the table. Oh, and did I mention that my landlady also covered electricty? Pretty epic, especially since the cabin wasn't well insulated and I had to run 2.5kW of heating that winter.

In the last two years, I have truly started to learn how black lives matter, and how little I understood my own racism in the past. I have learned about social justice, and become keenly aware of my failings. I have gained true confidence in my skills, and become comfortable in my body for the first time in my life. I have felt my socialist/anarchist heart begin to blossom as I notice the Democratic party repeatedly snatch defeat from the jaws of victory.

And, shortly after my birthday in 2014, I met the woman who has become the love of my life. She had to exercise both persistence and patience. I was wounded and avoiding romance, sex, dating. She had to convince me that a lesbian, even a trans-friendly lesbian, could be interested in an androgyne who still had and wasn't particularly inclined to get rid of eir penis. But, she exercised that persistence, and she waited patiently, while over the course of months I fell in love and I healed. Now we talk of our sixty year plan.

I will miss Austin. I will miss the people here. I will miss all of my bike routes and the restaurants and the events. I will miss the familiarity. And I feel guilt, leaving all of you to stay and stand against the legislature.

But for this woman, where she goes my heart shall follow.

## Nix Development Environments

Posted on Mon Nov 28 16:15:00 UTC 2016 by Savanni D'Gerinel

nix-shell, the command that creates a subshell after evaluating any nix expression, has a lot of uses. I found it very useful in my devops work when I had multiple environments to administer, but had to use different tools for each. The shell provides excellent help in isolating my required tools to the environments involved.

A trick, though, lay in learning how to acquire those tools when the tools were not available in the nixos channel. I figured it out, and so here is the example for one of the environments I was administering. Note that I include both Linux and Darwin builds, because I wanted to offer the nix environment to my replacement at the company.

• Packer -- 0.10.1
• Terraform -- 0.7.4
• Ansible 2
• Python 2.7

We were deploying in Amazon AWS. I used Packer to build the custom images that we were deploying. Autoscaling works a lot better if it has a complete image that only has to be started (the Crops, i.e., the systems that can be replaced almost instantly and thus do get replaced regularly). I love Terrafrom because I was able to describe everything I was doing in AWS using the tool. Ansible is present for those systems that get reconfigured regularly (primarily the Cattle machines, things that can be rebuilt from just the devops scripts, but that I do not want to terminate). Python 2.7 is present to support Ansible, though it is sometimes convenient to have at hand.

Neither Packer nor Terraform were available in my Nix channel, so I had to build derivations for those. The process is non-obvious until it is done. Here are my scripts for them. At the time I wrote these scripts, I was running NixOS 16.03, however I still use the same scripts after having upgraded to NixOS 16.09.

nix-deps/packer.nix

{ pkgs ? import <nixpkgs> {},
stdenv ? pkgs.stdenv }:

let
# suggestion from @clever of #nixos
package =
if stdenv.system == "x86_64-linux" then "packer_0.10.1_linux_amd64.zip"
else if stdenv.system == "x86_64-darwin" then "packer_0.10.1_darwin_amd64.zip"
else abort "unsupported platform";
checksum =
if stdenv.system == "x86_64-linux" then "7d51fc5db19d02bbf32278a8116830fae33a3f9bd4440a58d23ad7c863e92e28"
else if stdenv.system == "x86_64-darwin" then "fac621bf1fb43f0cbbe52481c8dfda2948895ad52e022e46f00bc75c07a4f181"
else abort "unsupported platform";
in
stdenv.mkDerivation rec {
name = "packer-${version}"; version = "0.10.1"; buildCommand = '' mkdir -p$out/bin
unzip $src mv packer$out/bin/packer
echo Installed packer to $out/bin/packer ''; src = pkgs.fetchurl { url = "https://releases.hashicorp.com/packer/0.10.1/${package}";
sha256 = checksum;
name = package;
};

buildInputs = [ pkgs.unzip ];
}

nix-deps/terraform.nix

{ pkgs ? import <nixpkgs> {},
stdenv ? pkgs.stdenv }:

let
# suggestion from @clever of #nixos
package =
if stdenv.system == "x86_64-linux" then "terraform_0.7.4_linux_amd64.zip"
else if stdenv.system == "x86_64-darwin" then "terraform_0.7.4_darwin_amd64.zip"
else abort "unsupported platform";
checksum =
if stdenv.system == "x86_64-linux" then "8950ab77430d0ec04dc315f0d2d0433421221357b112d44aa33ed53cbf5838f6"
else if stdenv.system == "x86_64-darwin" then "21c8ecc161628ecab88f45eba6b5ca1fbf3eb897e8bc951b0fbac4c0ad77fb04"
else abort "unsupported platform";
in
stdenv.mkDerivation rec {
name = "terraform-${version}"; version = "0.7.4"; buildCommand = '' mkdir -p$out/bin
unzip $src mv terraform$out/bin/terraform
echo Installed terraform to $out/bin/terraform ''; src = pkgs.fetchurl { url = "https://releases.hashicorp.com/terraform/0.7.4/${package}";
sha256 = checksum;
name = package;
};

buildInputs = [ pkgs.unzip ];
}

The structure of each script is relatively straightforward.

• declare that pkgs and stdenv are both required, as well as how to get them if they are absent
• based on the OS, declare what package I want to download and the relevant checksum
• declare the name and version of the derivation
• create the custom build command

In many cases, the default build commands works perfectly, but that only works for projects that have to be built with autoconfig or with Stack (and possibly some other languages). Both Terraform and Packer are binaries, and so it is necessary for me to specify the build for the derivation.

In this case, the build is simply to unzip the downloaded package (specified in $src) and copy the executable into the destination (which has a root at$out). It is vital that the executable end up in the bin/ directory. I am not sure of the mandated directory structure of a derivation, but I know that derivations that did not include the bin/ directory would fail. I assume that they failed because there was no executable to add to the path.

• specify precisely how to get the source package. In this case, through the fetchurl tool.
• specify additional build inputs. These have to be somewhere in the nix namespace. pkgs.unzip refers to nixpkgs.unzip in the standard channel.

Both of the files above must go in a subdirectory. I named the subdirectory nix-deps/. Some subtle interaction will cause an infinite recursion if the two files are included in the root directory of your project.

With those present, it is time to build the nix-shell command:

shell.nix

let
pkgs = import <nixpkgs> {};
stdenv = pkgs.stdenv;
terraform = import nix-deps/terraform.nix {};
packer = import nix-deps/packer.nix {};

in stdenv.mkDerivation {
name = "v2-devops";

buildInputs = [ pkgs.ansible2
terraform
packer
pkgs.python
pkgs.python27Packages.alembic
pkgs.python27Packages.boto
pkgs.python27Packages.psycopg2
pkgs.awscli
];
}

The only difficult part here was for me to figure out how to import my Terraform and Packer derivations. I handle that with the import nix-deps/<package>.nix {} lines. The result of each import statement is a derivation, and so it is valid to include in buildInputs.

buildInputs again just lists the packages that must be included in this derivation. So, I included all of the packages that I use directly.

Thus, from the root directory of my devops folder, I can simply run nix-shell and have exactly the version of Terraform, Packer, Ansible, and Python that I want. This also means that I can have completely different versions for a different devops repository (I was actually administering three different clouds, all with different standards). And, possibly best of all, if I could convince my co-workers to use Nix (the tool, not the operating system), they would have had a trivial way to set up their development environments, also.


text:
# Image of the Burau representation at $d$-th roots of unity

### Abstract

We show that the image of the braid group under the monodromy action on the homology of a cyclic covering of degree $d$ of the projective line is an arithmetic group provided the number of branch points is sufficiently large compared to the degree $d$. This is deduced by proving the arithmeticity of the image of the braid group on $n+1$ letters under the Burau representation evaluated at $d$-th roots of unity when $n\geq 2d$.

Note: To view the article, click on the URL link for the DOI number.

• [Abd] M. N. Abdulrahim, "Complex specializations of the reduced Gassner representation of the pure braid group," Proc. Amer. Math. Soc., vol. 125, iss. 6, pp. 1617-1624, 1997.
@article {Abd, MRKEY = {1422839},
TITLE = {Complex specializations of the reduced {G}assner representation of the pure braid group},
JOURNAL = {Proc. Amer. Math. Soc.},
FJOURNAL = {Proceedings of the American Mathematical Society},
VOLUME = {125},
YEAR = {1997},
NUMBER = {6},
PAGES = {1617--1624},
ISSN = {0002-9939},
CODEN = {PAMYAR},
MRCLASS = {20F36 (20C15)},
MRNUMBER = {1422839},
MRREVIEWER = {E. Formanek},
ZBLNUMBER = {0872.20035},
DOI = {10.1090/S0002-9939-97-04081-1},
}
• [Abd2] M. N. Abdulrahim, "A faithfulness criterion for the Gassner representation of the pure braid group," Proc. Amer. Math. Soc., vol. 125, iss. 5, pp. 1249-1257, 1997.
@article {Abd2, MRKEY = {1389500},
TITLE = {A faithfulness criterion for the {G}assner representation of the pure braid group},
JOURNAL = {Proc. Amer. Math. Soc.},
FJOURNAL = {Proceedings of the American Mathematical Society},
VOLUME = {125},
YEAR = {1997},
NUMBER = {5},
PAGES = {1249--1257},
ISSN = {0002-9939},
CODEN = {PAMYAR},
MRCLASS = {20F36 (20C15)},
MRNUMBER = {1389500},
MRREVIEWER = {Vitaly A. Roman{\cprime}kov},
ZBLNUMBER = {0868.20034},
DOI = {10.1090/S0002-9939-97-03827-6},
}
• [A’C] N. A’Campo, "Tresses, monodromie et groupes symplectique," Comment. Math. Helv., vol. 54, pp. 318-327, 1987.
@article{A'C,
author={A'Campo, N.},
TITLE={Tresses, monodromie et groupes symplectique},
JOURNAL={Comment. Math. Helv.},
VOLUME={54},
YEAR={1987},
PAGES={318--327},
ZBLNUMBER = {0441.32004}
}
• [Al-Car-Tol] D. Allcock, J. A. Carlson, and D. Toledo, "The complex hyperbolic geometry of the moduli space of cubic surfaces," J. Algebraic Geom., vol. 11, iss. 4, pp. 659-724, 2002.
@article {Al-Car-Tol, MRKEY = {1910264},
AUTHOR = {Allcock, Daniel and Carlson, James A. and Toledo, Domingo},
TITLE = {The complex hyperbolic geometry of the moduli space of cubic surfaces},
JOURNAL = {J. Algebraic Geom.},
FJOURNAL = {Journal of Algebraic Geometry},
VOLUME = {11},
YEAR = {2002},
NUMBER = {4},
PAGES = {659--724},
ISSN = {1056-3911},
MRCLASS = {32G20 (11F23 14J10 14J15 14K30 32M15 32Q45)},
MRNUMBER = {1910264},
MRREVIEWER = {I. Dolgachev},
ZBLNUMBER = {1080.14532},
DOI = {10.1090/S1056-3911-02-00314-4},
}
• [Al-Hal] D. Allcock and C. Hall, "Monodromy groups of Hurwitz-type problems," Adv. Math., vol. 225, iss. 1, pp. 69-80, 2010.
@article {Al-Hal, MRKEY = {2669349},
AUTHOR = {Allcock, Daniel and Hall, Chris},
TITLE = {Monodromy groups of {H}urwitz-type problems},
VOLUME = {225},
YEAR = {2010},
NUMBER = {1},
PAGES = {69--80},
ISSN = {0001-8708},
MRCLASS = {14H30 (14D05 57M10 57M12)},
MRNUMBER = {2669349},
MRREVIEWER = {Michael Friedman},
ZBLNUMBER = {1080.14532},
DOI = {10.1016/j.aim.2010.02.013},
}
• [Ba-Mi-Se] H. Bass, J. Milnor, and J. -P. Serre, "Solution of the congruence subgroup problem for ${ SL}_{n}\,(n\geq 3)$ and ${ Sp}_{2n}\,(n\geq 2)$," Inst. Hautes Études Sci. Publ. Math., vol. 33, pp. 59-137, 1967.
@article {Ba-Mi-Se, MRKEY = {0244257},
AUTHOR = {Bass, H. and Milnor, J. and Serre, J.-P.},
TITLE = {Solution of the congruence subgroup problem for {${\rm SL}\sb{n}\,(n\geq 3)$} and {${\rm Sp}\sb{2n}\,(n\geq 2)$}},
JOURNAL = {Inst. Hautes Études Sci. Publ. Math.},
FJOURNAL = {Institut des Hautes Études Scientifiques. Publications Mathématiques},
VOLUME = {33},
YEAR = {1967},
PAGES = {59--137},
ISSN = {0073-8301},
MRCLASS = {14.50 (20.00)},
MRNUMBER = {0244257},
MRREVIEWER = {R. Steinberg},
ZBLNUMBER = {0174.05203},
URL = {http://www.numdam.org/item?id=PMIHES_1967__33__59_0},
}
• [Beu-Hec] F. Beukers and G. Heckman, "Monodromy for the hypergeometric function $_nF_{n-1}$," Invent. Math., vol. 95, iss. 2, pp. 325-354, 1989.
@article {Beu-Hec, MRKEY = {0974906},
AUTHOR = {Beukers, F. and Heckman, G.},
TITLE = {Monodromy for the hypergeometric function {$\sb nF\sb {n-1}$}},
JOURNAL = {Invent. Math.},
FJOURNAL = {Inventiones Mathematicae},
VOLUME = {95},
YEAR = {1989},
NUMBER = {2},
PAGES = {325--354},
ISSN = {0020-9910},
CODEN = {INVMBH},
MRCLASS = {11F99 (12H05 20F38 20G20 33A35)},
MRNUMBER = {0974906},
MRREVIEWER = {A. L. Onishchik},
ZBLNUMBER = {0663.30044},
DOI = {10.1007/BF01393900},
}
• [Bir] J. S. Birman, Braids, Links, and Mapping Class Groups, Princeton, N.J.: Princeton Univ. Press, 1974, vol. 82.
@book {Bir, MRKEY = {0375281},
AUTHOR = {Birman, Joan S.},
TITLE = {Braids, Links, and Mapping Class Groups},
NOTE = {Ann. of Math. Stud.},
VOLUME={82},
PUBLISHER = {Princeton Univ. Press},
YEAR = {1974},
PAGES = {ix+228},
MRCLASS = {55A25},
MRNUMBER = {0375281},
MRREVIEWER = {Wilbur Whitten},
ZBLNUMBER = {0305.57013},
}
• [Bor-Ti] A. Borel and J. Tits, "Groupes réductifs," Inst. Hautes Études Sci. Publ. Math., vol. 27, pp. 55-150, 1965.
@article {Bor-Ti, MRKEY = {0207712},
AUTHOR = {Borel, Armand and Tits, Jacques},
TITLE = {Groupes réductifs},
JOURNAL = {Inst. Hautes Études Sci. Publ. Math.},
FJOURNAL = {Institut des Hautes Études Scientifiques. Publications Mathématiques},
VOLUME = {27},
YEAR = {1965},
PAGES = {55--150},
ISSN = {0073-8301},
MRCLASS = {14.50 (20.75)},
MRNUMBER = {0207712},
MRREVIEWER = {F. D. Veldkamp},
ZBLNUMBER = {0145.17402},
DOI = {10.1007/BF02684375},
}
• [Del-Mos] P. Deligne and G. D. Mostow, "Monodromy of hypergeometric functions and nonlattice integral monodromy," Inst. Hautes Études Sci. Publ. Math., vol. 63, pp. 5-89, 1986.
@article {Del-Mos, MRKEY = {0849651},
AUTHOR = {Deligne, P. and Mostow, G. D.},
TITLE = {Monodromy of hypergeometric functions and nonlattice integral monodromy},
JOURNAL = {Inst. Hautes Études Sci. Publ. Math.},
FJOURNAL = {Institut des Hautes Études Scientifiques. Publications Mathématiques},
VOLUME = {63},
YEAR = {1986},
PAGES = {5--89},
ISSN = {0073-8301},
CODEN = {PMIHA6},
MRCLASS = {22E40 (32G20 33A30)},
MRNUMBER = {0849651},
MRREVIEWER = {Shigeaki Tsuyumine},
ZBLNUMBER = {0615.22008},
DOI = {10.1007/BF02831622},
}
• [Gr-Sch] P. A. Griffiths and W. Schmid, "Recent developments in Hodge theory: a discussion of techniques and results," in Discrete Subgroups of Lie Groups and Applications to Moduli, Bombay: Oxford Univ. Press, 1975, pp. 31-127.
@incollection{Gr-Sch,
author={Griffiths, P. A. and Schmid, W.},
TITLE={Recent developments in \hbox{H}odge theory: a discussion of techniques and results},
BOOKTITLE={Discrete Subgroups of Lie Groups and Applications to Moduli},
VENUE={Intern. Colloq., Bombay, 1973},
YEAR={1975},
PAGES={31--127},
PUBLISHER={Oxford Univ. Press},
MRNUMBER = {0419850},
ZBLNUMBER = {0355.14003},
}
• [Gr-Lu] F. Grunewald and A. Lubotzky, "Linear representations of the automorphism group of a free group," Geom. Funct. Anal., vol. 18, iss. 5, pp. 1564-1608, 2009.
@article {Gr-Lu, MRKEY = {2481737},
AUTHOR = {Grunewald, Fritz and Lubotzky, Alexander},
TITLE = {Linear representations of the automorphism group of a free group},
JOURNAL = {Geom. Funct. Anal.},
FJOURNAL = {Geometric and Functional Analysis},
VOLUME = {18},
YEAR = {2009},
NUMBER = {5},
PAGES = {1564--1608},
ISSN = {1016-443X},
CODEN = {GFANFB},
MRCLASS = {20F28 (20E05 20G05)},
MRNUMBER = {2481737},
MRREVIEWER = {Valerij G. Bardakov},
ZBLNUMBER = {1175.20028},
DOI = {10.1007/s00039-009-0702-2},
}
• [Long] D. D. Long, "On the linear representation of braid groups," Trans. Amer. Math. Soc., vol. 311, iss. 2, pp. 535-560, 1989.
@article {Long, MRKEY = {943606},
AUTHOR = {Long, D. D.},
TITLE = {On the linear representation of braid groups},
JOURNAL = {Trans. Amer. Math. Soc.},
FJOURNAL = {Transactions of the American Mathematical Society},
VOLUME = {311},
YEAR = {1989},
NUMBER = {2},
PAGES = {535--560},
ISSN = {0002-9947},
CODEN = {TAMTAM},
MRCLASS = {20F36 (32B30 57M25)},
MRNUMBER = {943606},
MRREVIEWER = {J. S. Birman},
ZBLNUMBER = {0714.20019},
DOI = {10.2307/2001141},
}
• [Looi] E. Looijenga, "Uniformization by Lauricella functions—an overview of the theory of Deligne-Mostow," in Arithmetic and Geometry Around Hypergeometric Functions, Basel: Birkhäuser, 2007, vol. 260, pp. 207-244.
@incollection {Looi, MRKEY = {2306154},
AUTHOR = {Looijenga, Eduard},
TITLE = {Uniformization by {L}auricella functions---an overview of the theory of {D}eligne-{M}ostow},
BOOKTITLE = {Arithmetic and Geometry Around Hypergeometric Functions},
SERIES = {Progr. Math.},
VOLUME = {260},
PAGES = {207--244},
PUBLISHER = {Birkhäuser},
YEAR = {2007},
MRCLASS = {33C65 (32G20 33-02)},
MRNUMBER = {2306154},
MRREVIEWER = {Martin Deraux},
ZBLNUMBER = {1120.33013},
DOI = {10.1007/978-3-7643-8284-1_8},
}
• [Looi2] E. Looijenga, "Prym representations of mapping class groups," Geom. Dedicata, vol. 64, iss. 1, pp. 69-83, 1997.
@article {Looi2, MRKEY = {1432535},
AUTHOR = {Looijenga, Eduard},
TITLE = {Prym representations of mapping class groups},
JOURNAL = {Geom. Dedicata},
FJOURNAL = {Geometriae Dedicata},
VOLUME = {64},
YEAR = {1997},
NUMBER = {1},
PAGES = {69--83},
ISSN = {0046-5755},
CODEN = {GEMDAT},
MRCLASS = {57M10 (14H10 20F38 57N05)},
MRNUMBER = {1432535},
MRREVIEWER = {Ronnie Lee},
ZBLNUMBER = {0872.57018},
DOI = {10.1023/A:1004909416648},
}
• [Mar] G. A. Margulis, Discrete Subgroups of Semisimple Lie Groups, New York: Springer-Verlag, 1991, vol. 17.
@book {Mar, MRKEY = {1090825},
AUTHOR = {Margulis, G. A.},
TITLE = {Discrete Subgroups of Semisimple {L}ie Groups},
SERIES = {Ergeb. Math. Grenzgeb.},
VOLUME = {17},
PUBLISHER = {Springer-Verlag},
YEAR = {1991},
PAGES = {x+388},
ISBN = {3-540-12179-X},
MRCLASS = {22E40 (20Hxx 22-02 22D40)},
MRNUMBER = {1090825},
ZBLNUMBER = {0732.22008},
}
• [Mc] C. T. McMullen, "Braid groups and Hodge theory," Math. Ann., vol. 355, iss. 3, pp. 893-946, 2013.
@article {Mc, MRKEY = {3020148},
AUTHOR = {McMullen, Curtis T.},
TITLE = {Braid groups and {H}odge theory},
JOURNAL = {Math. Ann.},
FJOURNAL = {Mathematische Annalen},
VOLUME = {355},
YEAR = {2013},
NUMBER = {3},
PAGES = {893--946},
ISSN = {0025-5831},
CODEN = {MAANA},
MRCLASS = {20F36 (14C30)},
MRNUMBER = {3020148},
ZBLNUMBER = {06149478},
DOI = {10.1007/s00208-012-0804-2},
}
• [Mos] G. D. Mostow, "Generalized Picard lattices arising from half-integral conditions," Inst. Hautes Études Sci. Publ. Math., vol. 63, pp. 91-106, 1986.
@article {Mos, MRKEY = {0849652},
AUTHOR = {Mostow, G. D.},
TITLE = {Generalized {P}icard lattices arising from half-integral conditions},
JOURNAL = {Inst. Hautes Études Sci. Publ. Math.},
FJOURNAL = {Institut des Hautes Études Scientifiques. Publications Mathématiques},
VOLUME = {63},
YEAR = {1986},
PAGES = {91--106},
ISSN = {0073-8301},
CODEN = { PMIHA6},
MRCLASS = {22E40 (32G20 33A30)},
MRNUMBER = {0849652},
MRREVIEWER = {Shigeaki Tsuyumine},
ZBLNUMBER = {0615.22009},
DOI = {10.1007/BF02831623},
}
• [Nor] M. V. Nori, "A nonarithmetic monodromy group," C. R. Acad. Sci. Paris Sér. I Math., vol. 302, iss. 2, pp. 71-72, 1986.
@article {Nor, MRKEY = {0832040},
TITLE = {A nonarithmetic monodromy group},
JOURNAL = {C. R. Acad. Sci. Paris Sér. I Math.},
FJOURNAL = {Comptes Rendus des Séances de l'Académie des Sciences. Série I. Mathématique},
VOLUME = {302},
YEAR = {1986},
NUMBER = {2},
PAGES = {71--72},
ISSN = {0249-6291},
CODEN = {CASMEI},
MRCLASS = {14D05 (14K15)},
MRNUMBER = {0832040},
MRREVIEWER = {J. S. Joel},
ZBLNUMBER = {0602.14025},
}
• [Pl-Ra] V. Platonov and A. Rapinchuk, Algebraic Groups and Number Theory, Boston, MA: Academic Press Inc., 1994, vol. 139.
@book{Pl-Ra, MRKEY={1278263},
AUTHOR = {Platonov, Vladimir and Rapinchuk, Andrei},
TITLE = {Algebraic Groups and Number Theory},
SERIES = {Pure and Applied Mathematics},
VOLUME = {139},
NOTE = {translated from the 1991 Russian original by Rachel Rowen},
YEAR = {1994},
PAGES = {xii+614},
ISBN = {0-12-558180-7},
MRCLASS = {11E57 (11-02 20Gxx)},
MRNUMBER = {1278263},
ZBLNUMBER = {0841.20046},
}
• [Ra] M. S. Raghunathan, "A note on generators for arithmetic subgroups of algebraic groups," Pacific J. Math., vol. 152, iss. 2, pp. 365-373, 1992.
@article {Ra, MRKEY = {1141802},
AUTHOR = {Raghunathan, M. S.},
TITLE = {A note on generators for arithmetic subgroups of algebraic groups},
JOURNAL = {Pacific J. Math.},
FJOURNAL = {Pacific Journal of Mathematics},
VOLUME = {152},
YEAR = {1992},
NUMBER = {2},
PAGES = {365--373},
ISSN = {0030-8730},
CODEN = {PJMAAI},
MRCLASS = {22E40 (20H20)},
MRNUMBER = {1141802},
MRREVIEWER = {Avner Ash},
ZBLNUMBER = {0793.20045},
DOI = {10.2140/pjm.1992.152.365},
}
• [Ra2] M. S. Raghunathan, Discrete Subgroups of Lie Groups, New York: Springer-Verlag, 1972, vol. 68.
@book {Ra2, MRKEY = {0507234},
AUTHOR = {Raghunathan, M. S.},
TITLE = {Discrete Subgroups of {L}ie Groups},
SERIES = {Ergeb. Math. Grenzgeb.},
VOLUME={68},
PUBLISHER = {Springer-Verlag},
YEAR = {1972},
PAGES = {ix+227},
MRCLASS = {22E40},
MRNUMBER = {0507234},
MRREVIEWER = {J. S. Joel},
ZBLNUMBER = {0254.22005},
DOI = {10.2140/pjm.1992.152.365},
}
• [Sar] P. Sarnak, Notes on thin groups, 2012.
@misc{Sar,
author={Sarnak, P.},
TITLE={Notes on thin groups},
NOTE={MSRI Hot Topics Workshop},
YEAR={2012} , URL ={http://www.msri.org/attachments/workshops/652_Sarnak-notes.pdf},
}
• [Sq] C. C. Squier, "The Burau representation is unitary," Proc. Amer. Math. Soc., vol. 90, iss. 2, pp. 199-202, 1984.
@article {Sq, MRKEY = {0727232},
AUTHOR = {Squier, Craig C.},
TITLE = {The {B}urau representation is unitary},
JOURNAL = {Proc. Amer. Math. Soc.},
FJOURNAL = {Proceedings of the American Mathematical Society},
VOLUME = {90},
YEAR = {1984},
NUMBER = {2},
PAGES = {199--202},
ISSN = {0002-9939},
CODEN = {PAMYAR},
MRCLASS = {20F36},
MRNUMBER = {0727232},
MRREVIEWER = {J. S. Birman},
ZBLNUMBER = {0542.20022},
DOI = {10.2307/2045338},
}
• [Ti] J. Tits, "Systèmes générateurs de groupes de congruence," C. R. Acad. Sci. Paris Sér. A-B, vol. 283, iss. 9, p. ai, a693-a695, 1976.
@article {Ti, MRKEY = {0424966},
AUTHOR = {Tits, Jacques},
TITLE = {Systèmes générateurs de groupes de congruence},
JOURNAL = {C. R. Acad. Sci. Paris Sér. A-B},
VOLUME = {283},
YEAR = {1976},
NUMBER = {9},
PAGES = {Ai, A693--A695},
MRCLASS = {20H05 (20G30)},
MRNUMBER = {0424966},
MRREVIEWER = {J. E. Humphreys},
ZBLNUMBER = {0381.14005},
}
• [Va] L. N. Vaservsteuin, "Structure of the classical arithmetic groups of rank greater than $1$," Mat. Sb., vol. 20, pp. 465-492, 1973.
@article {Va, MRKEY = {0349864},
AUTHOR = {Vaser{š}te{\u\i}n, L. N.},
TITLE = {Structure of the classical arithmetic groups of rank greater than {$1$}},
JOURNAL = {Mat. Sb.},
VOLUME = {20},
YEAR = {1973},
PAGES = {465-492},
MRCLASS = {20H05 (20H10)},
MRNUMBER = {0349864},
MRREVIEWER = {K. W. Roggenkamp},
ZBLNUMBER = {0291.14016},
DOI = {10.1070/SM1973v020n03ABEH001885},
}
• [Ve] T. N. Venkataramana, "On systems of generators of arithmetic subgroups of higher rank groups," Pacific J. Math., vol. 166, iss. 1, pp. 193-212, 1994.
@article {Ve, MRKEY = {1306038},
AUTHOR = {Venkataramana, T. N.},
TITLE = {On systems of generators of arithmetic subgroups of higher rank groups},
JOURNAL = {Pacific J. Math.},
FJOURNAL = {Pacific Journal of Mathematics},
VOLUME = {166},
YEAR = {1994},
NUMBER = {1},
PAGES = {193--212},
ISSN = {0030-8730},
CODEN = {PJMAAI},
MRCLASS = {22E40 (20G15)},
MRNUMBER = {1306038},
MRREVIEWER = {Alexander Starkov},
ZBLNUMBER = {0822.22005},
DOI = {10.2140/pjm.1994.166.193},
}

## Authors

T. N. Venkataramana

School of Mathematics, Tata Institute of Fundamental Research, Homi Bhabha Road, Colaba, Mumbai, 40005, India