一歩前進

プログラミングに関する雑多なメモ

HaskellのJavadoc, Haddockを使う

HaskellJavadocやRDocに相当するドキュメンテーション生成ツールHaddockを使ってみます。

インストール

cabalが便利なのでcabalを使います。
まず、パッケージ情報を更新しておきます。

$ cabal update

古いパッケージをアップグレードしておきたい場合は、

$ cabal install --upgrade-dependencies

とします。 では、haddockをインストールしてみます。

$ cabal install haddock
Resolving dependencies...
Downloading haddock-2.13.2.1...
Configuring haddock-2.13.2.1...
cabal: The program alex version >=2.3 is required but the version of
/Users/succzero/.cabal/bin/alex could not be determined.
Failed to install haddock-2.13.2.1
cabal: Error: some packages failed to install:
haddock-2.13.2.1 failed during the configure step. The exception was:
ExitFailure 1

おや、エラーが出ました。どうやらalexのバージョンが古いようです。最新にアップグレードされているはずなのに、なぜ?
alexのバージョンを確認しましょう。

$ alex -v
dyld: Library not loaded: /opt/local/lib/gcc47/libgcc_s.1.dylib
  Referenced from: /Users/succzero/.cabal/bin/alex
  Reason: image not found

実行すらされない:(
そういえば、gcc47を消してgcc48に切り替えていたので、依存ライブラリをロード出来るわけがないのですね。ビルドし直します。
再インストールするときはcabal install --reinstallとします。

$ cabal install --reinstall alex
Resolving dependencies...
Downloading alex-3.1.3...
...
Linking dist/build/alex/alex ...
Installing executable(s) in /Users/succzero/.cabal/bin
Installed alex-3.1.3

ビルドできました。

$ alex -v
Alex version 3.1.3, (c) 2003 Chris Dornan and Simon Marlow

れっつリトライ

$ cabal install haddock

ドキュメントを書いてみる

ドキュメントコメントは、{- | ... }-- | の形式で記述します。
通常のコメントに対して、コメントの先頭行に|を加えればとりあえずOK。

{- |
Module      : Main
Description : ドキュメンテーションテスト
Copyright   : (c) succzero, 2014
License     : GPL-3
Maintainer  : succzero@gmaill.com
Stability   : experimental
Portability : POSIX

ここにモジュールの詳細な記述を書く.
-}
module Main where

-- | 'Hello, World'を表示する.
main :: IO ()
main = putStrLn "Hello, World"

このソースコードから実際にドキュメントを生成してみます。

$ haddock -h Main.hs -o doc

-hオプションを指定すると、htmlでドキュメントを生成します。-c CSSファイルパスで指定したCSSファイルを適用することも出来ます。
-oオプションは、ドキュメントの生成先ディレクトリを指定します。

生成されたものがこちら。

f:id:succzero:20140225012750p:plain

どうやら日本語がうまく使えないようです。

日本語文字を削除して、他のマークアップも試してみます。

{-# HADDOCK Markdown #-}
{- |
Module      : Main
Description : This is documentation tests.
Copyright   : (c) succzero, 2014
License     : GPL-3
Maintainer  : succzero@gmaill.com
Stability   : experimental
Portability : POSIX

Here is a longer description of this module.
-}
module Main where

-- | Display the string 'Hello, World'.
--
-- __ Bold(strong) __, /Emphasis(italic)/, @Monospace: f x = x + 1@
--
-- Code Blocks:
--
-- @
--     fix f = f (fix f) 
-- @
-- 
--
-- Itemize:
--
--     * foo
--
--     * bar
main :: IO ()
main = putStrLn "Hello, World"

生成した結果は以下のようになりました。 ボールドがうまく反映されていないのは何故だろう。

f:id:succzero:20140225020502p:plain

20140225021141

マニュアル

Haddock User Guide
http://www.haskell.org/haddock/doc/html/index.html

KeyRemap4MacBookでキーのリピートを速くする

Macを使っていてカーソル移動や文字を削除するときの動作が遅いなぁ、と思ったことはありませんか? そこで、KeyRemap4MacBookです。

1. インストール

(1) まずはKeyRemap4MacBookをダウンロードします

KeyRemap4MacBook

https://pqrs.org/macosx/keyremap4macbook/index.html.ja

(2) ダウンロードしたdmgファイルをダブルクリックでマウントします

pkgファイルが出てきます。
これをダブルクリックすればいいのですが、pkgファイルだと何がインストールされるのか気になります。もしかすると/usr/binの直下に変なものが入ってシステムがぐちゃぐちゃになるかもしれないじゃないですか!
そこでpkgutilコマンドを次のように使用します。

pkgutil --payload-files /Volumes/KeyRemap4MacBook-9.3.0/KeyRemap4MacBook.pkg

実行結果:

./Applications
./Applications/KeyRemap4MacBook.app
./Applications/KeyRemap4MacBook.app/Contents
./Applications/KeyRemap4MacBook.app/Contents/_CodeSignature
...
./Applications/KeyRemap4MacBook.app/Contents/Resources/vkopenurldef.xml
./Library
./Library/LaunchAgents
./Library/LaunchAgents/org.pqrs.KeyRemap4MacBook.server.plist

要約すると、インストールされるものは次の2つのようです。これなら安心ですね。

  • /Applications/KeyRemap4MapBook.app
  • /Library/LaunchAgents/org.pqrs.KeyRemap4MacBook.server.plist

(3) pkgをダブルクリックしてインストールする

気を取り直して、pkgファイルを実行します。

2. セットアップ

まず、Launchpad画面もしくはApplicationフォルダからKeyRemap4MacBookを起動します。

f:id:succzero:20140224020725p:plain

キーリピート速度の変更

Key Repeatタブを開き、次の項目を、好きな値に変更します。

  • Delay Until Repeat (リピート入力認識までの時間)
    • 500ms → 200ms (※)
  • Key Repeat (キーのリピート間隔)
    • 83ms → 13ms

(※)200ms以下の値を指定しても、実質的に200ms以下にはならないよう制限をしているようです
https://groups.google.com/forum/#!msg/keyremap4macbook-ja/l1bvnzVL-Gc/9RuMwT6nNlUJ

これで(Vim以外のエディタを使っているときの)カーソル移動や文字の削除時のストレスが減りました。

キー同時押しの閾値を下げる

同じくKey Repeatタブ画面の中にある、Double Press Modifier -> Recognition Thresholdの値を下げると、連続で複数のキーを押した時に、同時押しと認識されにくくなります。
これによって、「Command を押してから x 」という操作が 「 Command + x 」と認識されてしまうのを防ぎます。

ghc-mod-3.1.5 depends on haskell-src-exts-1.14.0 which failed to install.

cabalからghc-modを入れようとしたら以下のようなエラーに遭遇しました。

cabal: Error: some packages failed to install:
ghc-mod-3.1.5 depends on haskell-src-exts-1.14.0 which failed to install.
haskell-src-exts-1.14.0 failed during the configure step. The exception was:
ExitFailure 1
hlint-1.8.57 depends on haskell-src-exts-1.14.0 which failed to install.

どうやらhaskell-src-extsというパッケージが入っていないことが原因らしい。 依存関係がうまく解決できていないようなので、手動で依存パッケージを入れていきます。 まずhaskell-src-extsをインストールします。

$ cabal install haskell-src-exts
...(中略)
setup: The program happy version >=1.17 is required but the version of
/Users/succzero/.cabal/bin/happy could not be determined.
Failed to install haskell-src-exts-1.14.0
cabal: Error: some packages failed to install:
haskell-src-exts-1.14.0 failed during the configure step. The exception was:
ExitFailure 1

エラーになりました。どうやらHaskellパーサーのhappyが必要なようです。ですが、このパッケージはMacPorts経由で入れていたのでした(パッケージ名はhs-happy)。

$ which happy
/opt/local/bin/happy

しかし、エラーメッセージをよくよく見ると、/Users/succzero/.cabal/bin/happy could not be determined.と出ており、.cabalにインストールされていないといけないようです。 というわけで、cabalからインストールします。

$ cabal install happy

インストールできたので、確認します。

$ which happy
/Users/succzero/.cabal/bin/happy

happyの位置が.cabal側を向くようになっているので意識しておいたほうがいいですね。むしろ、Haskell関係のパッケージはcabalに集中させたほうがいいかもしれません。 ちなみに、cabalからインストールしたhappyのバージョンの方が最新でした。

$ ~/.cabal/bin/happy --version
Happy Version 1.19.3 Copyright (c) 1993-1996 Andy Gill, Simon Marlow (c) 1997-2005 Simon Marlow
$ /opt/local/bin/happy --version
Happy Version 1.18.10 Copyright (c) 1993-1996 Andy Gill, Simon Marlow (c) 1997-2005 Simon Marlow

さて、気を取り直してもう一度。

$ cabal install haskell-src-exts
...
Registering haskell-src-exts-1.14.0...
Installed haskell-src-exts-1.14.0

今度はインストール出来ました。 最初のエラーメッセージでhlint-1.8.57 depends on haskell-src-exts-1.14.0 which failed to installと表示されていたので、次にhlintもインストールしておきます。

実はここで間違えて、hlintではなくhintパッケージを入れてしまいました。

$ cabal install hint

どうやらHaskellインタプリタのようです。 http://projects.haskell.org/hint/ インタプリタなのでHaskellソースコードを解釈できるわけですね。実行時になんらかのHaskellソースファイルをロードして、指定された関数を解釈させてやれば、動的なモジュールロードとかリフレクションみたいな使い方が出来そうです。これは面白そう!

話を戻して、hlintをインストールします。

$ cabal install hlint
...
Registering hlint-1.8.57...
Installed hlint-1.8.57

ここでようやく本命のghc-modをインストールします。

$ cabal install ghc-mod
...
Registering ghc-mod-3.1.5...
Installed ghc-mod-3.1.5
$ which ghc-mod
/Users/succzero/.cabal/bin/ghc-mod

無事、ghc-modをインストールできました。

[Mac] perlbrewでERROR: Failed to retrieve patchperl executable.が出たときの対処

Mac上でのperlbrewで"ERROR: Failed to retrieve patchperl executable"というエラーが出たので回避策をメモします。 どうやら、MacPortsからインストールしたwgetに関連するエラーのようで、これを使わないようにすることでエラーを回避できました。

エラーのログ:

$ \curl -L http://install.perlbrew.pl | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0   315    0     0    0     0      0      0 --:--:--  0:00:03 --:--:--     0
100  1020  100  1020    0     0    175      0  0:00:05  0:00:05 --:--:--  3763

## Download the latest perlbrew

## Installing perlbrew
perlbrew is installed: ~/perl5/perlbrew/bin/perlbrew

perlbrew root (~/perl5/perlbrew) is initialized.

Append the following piece of code to the end of your ~/.zshenv and start a
new shell, perlbrew should be up and fully functional from there:

    source ~/perl5/perlbrew/etc/bashrc

Simply run `perlbrew` for usage details.

Happy brewing!

## Installing patchperl

ERROR: Failed to retrieve patchperl executable.

perlbrew本体のインストールは出来ているものの、その先のpatchperlのインストールで失敗しているようです。以下のやりとりをみると、どうやらMacPortsからインストールしたwgetがよろしくないようです。

"Installing perlbrew on OS X Mavericks (10.9.1) and macports"
http://stackoverflow.com/questions/20921886/installing-perlbrew-on-os-x-mavericks-10-9-1-and-macports

SSL証明書関連の問題かと思い、wget側でもcurlがみている証明書を参照するようにしたのですが、どうやら違う模様。

対処

方法その1

MacPortsのactivate, deactivateを使って、一時的にwgetを使わないようにする方法です。

(1) MacPortsdeactivateコマンドでwgetをオフにしておきます。

 $ sudo port deactivate wget
Password:
--->  Deactivating wget @1.14_5+ssl+universal
--->  Cleaning wget

(2) 次に、さきほどインストールしたperlbrewを一旦削除して、クリーンな状態に戻しておきます。

$ rm -rf ~/perl5/perlbrew

(3) ここでperlbrewをインストールします。今度はうまくいきました。

$ \curl -L http://install.perlbrew.pl | bash
... (中略)
Happy brewing!

## Installing patchperl

## Done.

(4) MacPortsを元に戻しておきます。

$ sudo port activate wget
--->  Computing dependencies for wget
--->  Activating wget @1.14_5+ssl+universal

To customize wget, you can copy /opt/local/etc/wgetrc.sample to /opt/local/etc/wgetrc     and then make changes.

--->  Cleaning wget

方法その2

方法1だと、perlbrewから何かインストールする度にwgetをdeactiveにする必要があります。スクリプトを作ってしまうのも手ですが、以下のエントリをみると、wgetとfetchの定義を削ればいいようです。wgetが無くても動くことは方法1で分かっているので、perlbrewを編集してみます。

「さくらのレンタルサーバに perlbrew」
http://www.naney.org/diki/d/2013-09-23-perlbrew.html

(1) perlbrewのバックアップを取る

cd ~/perl5/perlbrew/bin
cp perlbrew perlbrew.bak

(2) perlbrewを編集する

適当なエディタでperlbrewを開きます。8行目あたりにやたらと長い1行が出てくるため、表示がうまくいかない場合は折り返しをオフにするといいでしょう。(vimの場合は:set nowrap)

次のような箇所を探します。

my%commands=(curl=>{test=>'--version >/dev/null 2>&1',get=>'--silent --location --fail -o - {url}',download=>'--silent --location --fail -o {output} {url}' },wget=>{test=>'--version >/dev/null 2>&1',get=>'--quiet -O - {url}',download=>'--quiet -O {output} {url}',},fetch=>{test=>'--version >/dev/null 2>&1',get=>'-o - {url}',download=>'{url}' });sub http_user_agent_program {...

上記のwgetfetchの定義箇所を削除して保存します。 (※ただし、cpanmとpatchperlで試した限りでは、fetchの定義を削らなくてもエラーにはなりませんでした。どうやらwget固有の問題のようですが、念のためfetchも定義から除外しておきます。)

これでcpanmも無事インストールできました。

perlbrew install-cpanm

cpanm is installed to

    /Users/succzero/perl5/perlbrew/bin/cpanm

余談

wgetを無効にしない状態では、cpanmに関してはperl -dで実行するとうまくインストールされます。ただし、patchperlについては以下のissueのように-dの有無によらず失敗します。

"perlbrew fails to install patchperl"
https://github.com/gugod/App-perlbrew/issues/350

perl -dのログ:

$ perl -d ./perlbrew.bak install-cpanm

Loading DB routines from perl5db.pl version 1.39_10
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(./perlbrew.bak:564): my $app = App::perlbrew->new(@ARGV);
  DB<1> r

/Users/succzero/perl5/perlbrew/bin/cpanm already exists, are you sure to override ? [y/N] [N] y

cpanm is installed to

    /Users/succzero/perl5/perlbrew/bin/cpanm

Debugged program terminated.  Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.

畳込関数fold:foldrとfoldlの違い (あるいはfold_right, fold_left)

畳込関数fold

リストに関する処理は、以下のようなパターンで処理することが多いです。

f []     = v
f (x:xs) = x ● f xs

上記は関数fにリストを与えた時、次のような処理を行います。

  • リストが空の場合:値vが返される
  • リストが空でない場合:先頭要素xと関数fを残りのリストxsに適用した結果に対して、何らかの演算●を適用したものが返される

このようなパターンを簡潔に記述するために畳み込み(fold)と呼ばれる関数を使うことが出来ます。1

例として、合計を取るsum関数の通常版とfold版を示します。ソースコードHaskellです。

sumの通常版

sum []     = 0
sum (x:xs) = x + sum xs

sumのfold版

sum = foldr (+) 0

foldは次の入力を受け取り、出力を返します。

  • 入力:
    • 2引数関数
    • アキュムレータの初期値
    • 畳み込み対象のリスト
  • 出力:
    • 最終的なアキュムレータ

ここで、アキュムレータとは畳み込みに用いる値であり、sumのfold版の例では0が初期値になります。 畳み込み関数の大まかな処理は以下のようになります。後述する右畳み込み、左畳み込みの図と合わせて読むと理解しやすいと思います。

  1. 2引数関数を以下の2つの引数で呼び出す:
    • アキュムレータの値
    • リストの先頭(あるいは最後)の要素
  2. その結果を新しいアキュムレータとする
  3. リストの次の要素を先頭(あるいは最後)とする
  4. 新しいアキュムレータとリストを使って、1.を繰り返す

畳み込みは右からでも左からでも可能です。

左畳み込み foldl (fold_left)

左畳み込みでは、リストの左側の要素から畳み込みを行っていきます。 sumのfoldl版を図で表すと以下のようになります(厳密ではありませんが、このような具合になると考えてください)。

f:id:succzero:20131207233749p:plain

ここで、入力と出力は以下のようになります。

  • 入力:
    • 2引数関数: +演算子
    • アキュムレータの初期値: 0
    • 畳み込み対象のリスト: [1,2,3]
  • 出力:
    • 最終的なアキュムレータ: 6

実際にfoldl関数を呼び出すときのコードは以下のようになります。

foldl (+) 0 [1,2,3]

ただし、

sum = foldl (+) 0

と定義しておき、

sum [1,2,3]

という形で呼び出したほうが使い勝手が良いでしょう。 これは部分適用と呼ばれるもので、関数の引数を一部分だけ指定したものを定義しておき、残りについては後から指定できるようになるものです。これによって、関数が再利用しやすくなります。

foldlは以下のように定義することができます。この定義と上図を見比べると、リストが空になるまでの過程がfoldl f v (x:xs) = foldl f (f v x) xsで、リストが空であるときの処理がfoldl f v [] = vであることが直感的に見て取れると思います。

foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f v []     = v
foldl f v (x:xs) = foldl f (f v x) xs

ここで、最初に示したリスト処理のパターンを再掲します。

f []     = v
f (x:xs) = x ● f xs

ここでのfはsum関数のような具体的な関数名を想定しており、●演算子は+や-等の具体的な2引数関数になります。具体的に置き換えると、sumの通常版になります。

sum []     = 0
sum (x:xs) = x + sum xs

このパターンと、前述したfoldlの定義とを見比べると、foldはリスト処理パターンを抽象的に定義したものであることが見て取れます。

右畳み込み foldr (fold_right)

右畳み込みでは、リストの右側から畳み込みを行っていきます。ただし、リストは左側からしか読めないため、結果的に見ると右側から畳み込んでいるようにみえる、ということです。 これはfoldrが末尾再帰ではなく通常の再帰になっているため、「概念的には」下図のように、まず上から下に向かって計算式`f x (foldr f v xs)を展開していき、リストが空になった時点で、下から上に向かって展開した式を計算していくため、右側から畳み込んでいるようにみえるのです。(実際は遅延評価されますが、このような具合になると考えてください)

f:id:succzero:20131207233937p:plain

以下のfoldrの定義と図を見比べると動きがわかると重います。

foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f v []       = v
foldr f v (x:xs) = f x (foldr f v xs)

末尾再帰

再帰関数は自分自身を呼び出すような関数ですが、中でも末尾再帰はその関数の最後のステップが自身の呼び出しになっているものを指します。 foldlはfoldl f (f v x) xsとなっており、(f v x)の部分を先に計算して結果をv2すると、最後に残るのはfoldl f v2 xs という自分自身の呼び出しになります。 一方、foldrは、f x (foldr f v xs)となっており、(foldr f v xs)の部分を計算してv2とすると、最後に残るのはf x v2となり自分自身ではありません。この残りを覚えておくためにスタックを用いる必要があります。 このように、関数を呼び出した後にスタックに覚えておかなければならないような計算がないことを末尾呼び出し(tail call)といい、そのような再帰呼び出しになっていることを末尾再帰といいます。

末尾再帰はスタックが不要になるだけでなく、コンパイラによってはループとしてコンパイルされるため高速になるというメリットもあります。

foldlとfoldrの違いと使い分け

foldlとfoldrは、畳み込みの方向と末尾再帰か否かという点が大きく異なります。 スタックを消費しない末尾再帰であるfoldlのほうが良さそうに見えますが、リストから新しいリストを構成するような処理の場合、リストは左方向にしか伸ばせないためfoldrのほうが有利なことがあります。また、foldrでは無限リストを扱えるという特徴もあります。

参考のため、左畳み込みと右畳み込みの関数と型を載せておきます。

畳み込みの方向 関数名
foldr (a -> b -> b) -> b -> [a] -> b
foldl (a -> b -> a) -> a -> [b] -> a

リストから新しいリストを構成するケースではfoldrのほうが有利

右畳み込みのほうが有利になるケースとして、map関数を自作してみます。 map関数はリストと関数が与えられた時、その関数をリストの要素1つ1つに適用していき、その結果を新たなリストとして返すものです。 まずfoldrを使って定義したmap関数です。

mapr f xs = foldr (\x acc -> (f x) : acc) [] xs

関数fとリストxsを受け取り、xsの先頭要素を2引数関数のxに束縛、初期アキュムレータである空リスト[]を2引数関数のaccに束縛し、fをxに適用した結果をaccに連結させていきます。 2引数関数の中身は畳み込むときに計算されていき、そのおかげでリストの右側の要素から処理されていくのでした。このおかげで、結果となるリストは元のリストと順番が同じになります。 なお、foldrの2引数関数は以下の順序で引数を取ります。 - 第一引数:リストの先頭要素 - 第二引数:アキュムレータ

次はfoldを使ったmap関数をみてみましょう。

mapl f xs = foldl (\acc x -> acc ++ [f x]) [] xs

foldlの2引数関数は以下の順序で引数を取ります。 - 第一引数:アキュムレータ - 第二引数:リストの先頭要素 foldrのときとは順番が逆になっているのがわかると思います。

ここで++という演算子が現れています。コンス(:)演算子が要素とリストを結合するのに対し、++はリストとリストを結合するものです。このため、左側に空リストがきても結合ができます。 使い方のイメージは以下のようになります。

[] ++ [1]
=> [1]
(([] ++ [1]) ++ [2])
=> [1, 2]
((([] ++ [1]) ++ [2]) ++ [3])
=> [1, 2, 3]

ただし、コンスに比べ、リスト同士の結合はパフォーマンスが悪いため、このようなケースではスタックの消費が許されるならfoldrを使ったほうがよいかもしれません。 なお、リストの要素の順番を反転させるような場合はfoldlの方が有利です。

rev :: [a] -> [a]
rev = foldl (\acc x -> x : acc) []

rev [1,2,3]
=> [3,2,1]

無限リストをfoldrで扱う(foldlでは扱えない)

Haskellではリストは遅延評価されるため、foldrであれば無限リストを扱うことができます。

foldr (\x acc -> x * 2 : acc) [] [1..]
=> [2,4,6,8,10,12,14,16,18,20... 

[1..] というのは[1,2,3,..と続く無限のリストを表します。上記ではこの無限のリストに対して、それぞれの要素を2倍にしたリストを返すということを行っています。

しかし、すべての2引数関数で無限リストが使えるわけではありません。どのような演算なら無限リストが扱えるようになるのでしょうか?

ここで先ほど言ったfoldlとfoldrの計算順序の話は忘れてください(笑)。Haskellは遅延評価を特徴とする言語です。すごく大雑把に言うと外側から評価していきます。 参考文献にあるfoldl, foldrの簡潔な表現をみていきます。

foldl (●) v [x0,x1,...,xn] = (...((v ● x0) ● x1) ...) ● xn
foldr (●) v [x0,x1,...,xn] = x0 ● (x1 ● (... (xn ● v)...))

リストの要素が無限にある場合、外側から見ていくとfoldlは内側の(v ● x0)に到達できないことが分かります。 一方、foldrは外側にあるx0の部分は計算できそうです。その結果をv0とすると、v0 ● (x1 ● (...と続くので、次はx1を計算してv1とします。このように計算していくと、v0 ● (v1 ● (v2 ● ... と計算が行えるので、●の中身によってはうまく結果を取り出せそうです。 ●が&&であった場合を考えます。&&の定義は以下のようになっています。

True  && x = x
False && _ = False

特に左側がFalseの場合、右側を無視しているところに注目です。ここで、さきほどのv0Falseであった場合、残りの(x1 ● (x2 ● ... は無視されるため無限リストが対象であっても結果が得られるというわけです。 また、先ほど示したfoldr (\x acc -> x * 2 : acc) [] [1..]という式は、●の中身が(\x acc -> x * 2 : acc)となっています。この演算なら、無限リスト内のすべての要素が評価し終わるまで計算できないということは無いため、随時計算していくことができます。 ●を(\x acc -> x * 2 : acc)とすると、

1 ● (2 ● (3 ● ...

という式になります。これを外側からみていくと

[2]
[2,4]
[2,4,6]
....

というような具合に、順次計算していけることが分かると思います。

参考文献

Graham Hutton 著, 山本和彦 訳.『プログラミングHaskell』. オーム社(2009).

プログラミングHaskell

プログラミングHaskell

1. 簡潔に記述するためだけではなく、数学的な性質を扱うことができるようになりますが、詳しいことは他の記事に委ねることにします。

Rubyのバージョン体系と安定版、開発版の見分け方

バージョン体系

(major).(minor).(teeny)

例:1.8.7

Rubyでは、major, minor, teenyはそれぞれ1桁の値です(今のところ)。

一般に、major、minor、teenyは以下のような意味を示します。

  • majorバージョンはアーキテクチャやコンセプトの変更、完全な書き換えをカウント
  • minorバージョンは大幅な仕様変更や機能追加をカウント
  • teenyバージョンは軽微な仕様変更、小さな機能追加等をカウント

※teenyバージョンは、マイクロバージョンと呼ばれることもあります

パッチレベル

1.8.5以降ではバグ修正パッチをカウントするパッチレベルが付与されています。
例:2.0.0p247

開発版、安定版

Ruby 1.8 まで
minor
奇数 開発版 1.7.*
偶数 安定版 1.8.*
Ruby 1.9 以降
teeny バージョン
0 開発版 1.9.0
0以外 安定版 1.9.3

参考:http://docs.ruby-lang.org/ja/2.0.0/method/Object/c/RUBY_VERSION.html
※ただし、2.0.0については安定版の扱いとなるようです。

SQL Server のインスタンス名

SQL Serverをインストールするときに、特にインスタンス名を指定していなければ以下のインスタンス名が適用されるらしい。

SQL Server Management Studioから、「接続のプロパティの表示」で、製品名からExpressかどうか判断できるし、インスタンス名が空かどうかで、デフォルトのインスタンス名が適用されるかどうかが分かります。

確認方法は、以下のページが参考になります。
http://exceedone.wordpress.com/2011/12/20/sql-server%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E5%90%8D%E3%82%92%E8%AA%BF%E3%81%B9%E3%82%8B%E6%96%B9%E6%B3%95%E3%80%82-2/