ushumpei’s blog

生活で気になったことを随時調べて書いていきます。

Reduxの勉強

Redux

ここを一通り読めばわかりそうだ!と思って読み始めたら、いきなりプレディクタブルステートコンテナとか言われてよく分かりません。

Redux is a predictable state container for JavaScript apps. Read Me | Redux

ステートは普通に状態でいいのだろうか?あまり知らないため、用語を使っていたらわけわからなくなると思いながら、とりあえず読み進めることにしました。

30分の動画があるためそれを見る。なんか10個くらいあるようです。(間違ってました、後述)

  1. ToDoアプリを用いて、画面の状態が一つのオブジェクト(State Tree)に対応していることの実演。
  2. State Treeはリードオンリーで、操作(type)とデータを持ったオブジェクト(Action)によって変更される。
  3. Pure FunctionとImpure Functionの違い。副作用がないこと(戻り値を返す以外の方法で出力を行わないことかな?)
  4. StateとActionを受け取り新しいStateを返すのがReducer、これはPure Functionになっている。だから同じStateとActionを入れれば同じStateが必ず得られることが保証される。(ちょっと英語怪しくなってきました...)
  5. 数字を増やしたり減らしたりするだけのCounter Reducerを例に、ReducerとTestの説明をしている。expect(...).toEqual(...)って感じで書いている。またReducerの実装上の注意など説明されていた(未定義なtypeのAction、stateのデフォルト値など)
  6. Reduxの導入と、Storeのもつメソッドの説明。ReduxのcreateStoreメソッドによってReducerを引数にStoreというものが作られている。StoreはsubscribeメソッドによってViewの書き換えを行なったり、stateを保持しているようだ。StoreにActionをdispatchメソッドによって食べさせることで保持しているstateが更新されている。こいつは副作用を担っているっぽいです。
  7. createStoreの実装に関する説明。getState、dispatch、subscribeの三つを提供してくれるがこれらが何をしているかを説明してくれた。subscribeがあまりわからない...内部に持つlisteners配列を更新するが、filter処理はなにをしている?
  8. renderにはReactを使おう!その際はコールバックを渡すのがいいよ、という説明。おそらく先ほどのsubscribeのおかげでStoreが変更を反映してくれているんだろうという程度の理解。
  9. テストにdeepFreezeを使ってイミュータブルな処理をちゃんと書こうという話かな?es6の記法(配列listに対して...listを使うことで中身を展開できる)をつかった小粋な書き方とか勉強になりました。
  10. 引き続きテストの話。Object.assignとes6...objectの記法の説明。自分の英語力だと3点リーダの記法がいいように聞こえたんだけどどうなんだ?

いまさら気がついたのですが、この動画30分ではなく30個の動画だったのですね...

30見ていると何も達成感がないのでとりあえずまとめとしてカウンターアプリを作ってみよう。

と思ったのですが、環境構築がうまくいかずに断念。webpackを勉強しないといけない。

感想

ビルドツールになぜか苦手意識があることが判明しました。なぜ嫌なのだろうか?webpackを調べつつ、Redux触っていきたいです、あわよくばElectronでアプリ作りたいです。

javascriptで波括弧を使ってconst値に分割代入

こんにちは。

クロスプラットフォームのデスクトップアプリがhtml、cssjavascriptで作れてしまうフレームワーク「Electron」をちょっと触ってみようと思ったのですが、「Hello, world」する前に気になったことをメモします。 (Electronとはあまり関係ない内容になっています)

疑問

とりあえずElectronの環境を整えました。

mkdir myapp
npm init -y
cd myapp
npm install electron-prebuilt --save-dev

あとは、Quick Start - Electronを参考に進めていきました。

ウィンドウを表示したり、閉じた時の挙動を制御するシステム系の設定をindex.jspackage.jsonmainプロパティで指定したファイル)に記述するのですが、いざコピペしてやろうと思ってサイトの内容を読んでいるといきなり3行目に以下の記述を見かけました。

const electron = require('electron');
// Module to control application life.
const {app} = electron;
...

constは定数定義で、ES6から使えるらしい、ということは知っていたのですが、

この波括弧{app}はなんなんだ?と思いました。

知らないと恥ずかしいのかもしれないので、いろいろ試してみました。

(以下ごちゃごちゃしています。結論はタイトルに書いてあります)

スコープ

とりあえずconstは関係ない、スコープの問題だろうと当たりをつけて以下のコードをchromeのコンソールで実行しました。

{hoge} = {hoge:'hogehoge'};
console.log(hoge);

確かにこれでもhogehogeがコンソールに出力されます。

constがどうとかではなく、左辺に波括弧の中にオブジェクトのプロパティを記述すると、右辺のオブジェクトが持っているプロパティの値を取り出すことができるという動きです。

左辺の波括弧の中のhogeが外側から参照できること、左辺のhogeに右辺の値が入っていることについて考えなければと思い、javascriptのオブジェクトの代入に関して調べてみました。

javascriptにおいてはオブジェクト型の代入は参照渡しになる、ということを聞いてもしかすると、と考え以下のコードを試してみました。

obj1 = {p1:{c:1}};
p1 = obj1.p1;
p1.cc = 2;
console.info(obj1);
console.info(p1);

obj2 = {p2:{c:1}};
var {p2} = obj2;
p2.cc = 2;
console.info(obj2);
console.info(p2);

二種類の方法を試したのですが違いはありませんでした。 もしかすると波括弧で囲えば値渡しになるとか考えたのですが、それは間違っていました。。。

感想

そもそもなんでこう書かれているかを探るために、Electronのドキュメントのgithubリポジトリをみてみました。

この記法に変更された時のプルリクエストを見ると、Destructing assignmentというコミットメッセージを発見しました!

ググってみると次のページが見つかります。

分割代入 - JavaScript | MDN

分割代入、という構文だったんですね、初めて知りました。

今日はここにたどり着くまでで消耗してしましました...

gnuplotとFFTW

勉強のため、gnuplotgnuplot homepage)とc言語のFFTW(Fastest Fourier Transform in the West.)ライブラリの環境を作ってみます。

gnuplot

gnuplotコマンドラインから使えるグラフィックユーティリティです。科学者や学生向けに数学の関数をヴィジュアル化する目的で作られました。

homebrewでインストールします。こちらを参考にしました。(gnuplotをHomebrewからインストールするときの手順

$ brew install gnuplot --with-aquaterm

aquatermはGUIです。gnuplotの出力を表示するために、インストール時点でオプションを追加します。

インストール完了後gnuplotコマンドで対話環境が起動します。まずはaquatermでsin(x)を表示してみましょう。

gnuplot> set terminal aqua
gnuplot> plot sin(x)

f:id:ushumpei:20160604174532p:plain

出力方式、出力先を設定することで、画像ファイルやhtmlのcanvasとして吐き出すことができます。

gnuplot> set terminal png
gnuplot> set output 'sin_x.png'
gnuplot> plot sin(x)

関数をデータとして吐き出したい場合は、

gnuplot> set table "gnuplot.sample"
gnuplot> set yrange [0:1]
gnuplot> set xrange [-5:5]
gnuplot> plot exp(- x * x / 2) / sqrt(2 * pi)
gnuplot> unset table

とすると、gnuplot.sampleファイルに関数の値が書き込まれます。

# Curve 0 of 1, 100 points
# Curve title: "exp(- x * x / 2) / sqrt(2 * pi)"
# x y type
-5  1.48672e-06  i
-4.89899  2.45106e-06  i
-4.79798  3.99989e-06  i
-4.69697  6.46117e-06  i
-4.59596  1.0331e-05  i
-4.49495  1.6351e-05  i
-4.39394  2.56161e-05  i
-4.29293  3.97238e-05  i
-4.19192  6.09759e-05  i
-4.09091  9.26476e-05  i
-3.9899  0.000139341  i
-3.88889  0.00020744  i
-3.78788  0.000305686  i
-3.68687  0.00044589  i
-3.58586  0.000643795  i
-3.48485  0.000920105  i
-3.38384  0.00130165  i
-3.28283  0.00182273  i
-3.18182  0.0025265  i
-3.08081  0.00346644  i
-2.9798  0.00470779  i
-2.87879  0.00632878  i
-2.77778  0.00842153  i
-2.67677  0.0110926  i
-2.57576  0.0144624  i
-2.47475  0.0186646  i
-2.37374  0.0238433  i
-2.27273  0.0301496  i
-2.17172  0.0377369  i
-2.07071  0.0467541  i
-1.9697  0.057338  i
-1.86869  0.069604  i
-1.76768  0.0836362  i
-1.66667  0.0994771  i
-1.56566  0.117117  i
-1.46465  0.136486  i
-1.36364  0.157443  i
-1.26263  0.179775  i
-1.16162  0.20319  i
-1.06061  0.227324  i
-0.959596  0.251742  i
-0.858586  0.275953  i
-0.757576  0.299423  i
-0.656566  0.32159  i
-0.555556  0.341892  i
-0.454545  0.359787  i
-0.353535  0.374774  i
-0.252525  0.386423  i
-0.151515  0.394389  i
-0.0505051  0.398434  i
 0.0505051  0.398434  i
 0.151515  0.394389  i
 0.252525  0.386423  i
 0.353535  0.374774  i
 0.454545  0.359787  i
 0.555556  0.341892  i
 0.656566  0.32159  i
 0.757576  0.299423  i
 0.858586  0.275953  i
 0.959596  0.251742  i
 1.06061  0.227324  i
 1.16162  0.20319  i
 1.26263  0.179775  i
 1.36364  0.157443  i
 1.46465  0.136486  i
 1.56566  0.117117  i
 1.66667  0.0994771  i
 1.76768  0.0836362  i
 1.86869  0.069604  i
 1.9697  0.057338  i
 2.07071  0.0467541  i
 2.17172  0.0377369  i
 2.27273  0.0301496  i
 2.37374  0.0238433  i
 2.47475  0.0186646  i
 2.57576  0.0144624  i
 2.67677  0.0110926  i
 2.77778  0.00842153  i
 2.87879  0.00632878  i
 2.9798  0.00470779  i
 3.08081  0.00346644  i
 3.18182  0.0025265  i
 3.28283  0.00182273  i
 3.38384  0.00130165  i
 3.48485  0.000920105  i
 3.58586  0.000643795  i
 3.68687  0.00044589  i
 3.78788  0.000305686  i
 3.88889  0.00020744  i
 3.9899  0.000139341  i
 4.09091  9.26476e-05  i
 4.19192  6.09759e-05  i
 4.29293  3.97238e-05  i
 4.39394  2.56161e-05  i
 4.49495  1.6351e-05  i
 4.59596  1.0331e-05  i
 4.69697  6.46117e-06  i
 4.79798  3.99989e-06  i
 4.89899  2.45106e-06  i
 5  1.48672e-06  i

ここでは一列目がx軸、二列目がy軸になっています。三列目はちょっと謎...

このデータを使ってグラフを表示するのも簡単にできます。

gnuplot> plot "gnuplot.sample"

f:id:ushumpei:20160616000500p:plain

FFTW

FFTWは離散フーリエ変換を計算するためのc言語のライブラリです。変換する関数は次元、入力サイズ、実数or虚数別が選べます。

$ brew install fftw

FFTWには離散フーリエ変換を扱うための関数や複素数データ型が用意されています。

FFTW does not use a fixed algorithm for computing the transform, but instead it adapts the DFT algorithm to details of the underlying hardware in order to maximize performance.

FFTWでは入力データに対して、毎回決まった変換アルゴリズムを適応するのではなく、最適化した変換アルゴリズムを用いて離散フーリエ変換を行う仕組みになっています。そのため、変換実行前に「プラン」というものを作成します。複素一次元離散フーリエ変換のプランを作成する関数を見てみましょう。

fftw_plan fftw_plan_dft_1d(int n, fftw_complex *in, fftw_complex *out, int sign, unsigned flags);

fftw_plan_dft_1dfftw_planを戻り値にもつ関数です。引数として次のものをとります;

  • int n: データサイズ
  • fftw_complex *in:入力データ配列
  • fftw_complex *out:出力データ配列
  • int signフーリエ変換(-1)、逆フーリエ変換(+1)かの設定。定数が用意されています。
  • unsigned flags:通常はFFTW_ESTIMATEをつかい、サイズが同じ変換を何回もし、初期化コスト(?)を気にしないならばFFTW_MEASUREを使うみたいです。

感想

力が尽きてしまい、フーリエ変換前後のグラフを出力することは断念しました。sinをフーリエ変換して、一本だけ立つことを確認するとか、関数の和がどんどん短形関数に近づいていく様をみるとか、やりたいです。

フーリエ変換の練習(前半)

f:id:ushumpei:20160612004725p:plain

フーリエ変換について知識がないため、ちょっと勉強してみます。証明的なものを載せていますが、考え方を学ぶためのメモなため正確なことを知りたい場合参考書を当たってください。フーリエ変換の雰囲気がわからなくて困っている場合はちょっとは役に立つと思います。(私も同じ状況なので)

フーリエ変換は関数を周波数で分解した表示に変換できるものです。分解の際に現れる各項は連続関数と定数の積ですが、これらの無限の和を考えることで、不連続な関数に関しても分解が得られるということが面白と思いました。通信関係をはじめとして、広い範囲での応用がされています。

元となった理論は、フーリエ級数の研究なのかと思います。フーリエ級数は周期関数に関する表示を与えるものでしたが、フーリエ変換では周期を無限と考えることで、その対象を広げたところが違いです。

考え方の核は、周期を無限と考えることと、関数空間に対して基底による分解を与える感じでしょうか?一部フーリエ級数と変わらないですが。

前提条件としては、微分積分線形代数(基底とかの話)、複素数(というかオイラーの公式)を知っていれば理解できそうです。

離散フーリエ変換など応用の方面でまだまだ研究されているようで2012年には従来の10倍の変換速度を誇るSFFTといったものも発表されたみたいですね。。。

ということで、数学の勉強方法ってどうするんだろう、としばらく悩んだのですが、ああ、証明を考えてみるのが一番理解できるな、と思い出しました。理解のためにまずはフーリエ級数を証明してみます。なので周期関数の空間について考えます。ちゃんとした参考書みないので記号は適当です、うまくいかなかったらすみません。

周期関数

周期  T の関数の空間を  F_{T} := \{\, f \,|\, f(x) = f(x + T) \} と定義します。

内積は、 \displaystyle {
(f * g) = \int_{0}^{T} f(x)g(x) dx
} で定義します。(内積であることは積分の性質からいけるはず)

 F_{T}の基底が、1(定値関数)、 s_{n}(x) = \sin(\frac{2n\pi x}{T}) c_{n}(x) = \cos(\frac{2n\pi x}{T})  (n \in (1, 2, ...)) になることを示せれば、任意の周期関数  f \in F_{T} は、

 {\displaystyle
f(x) = c + \sum_{n=1}^{\infty} ( a_{n}s_{n}(x) +  b_{n}c_{n}(x) )
}

という形で表せることがわかります。

証明

前半

基底であることを示すには、一次独立と生成系であることを言わなければいけません。

まずは一次独立を示すために、それぞれの基底候補が直交していることを示します。

 \displaystyle{
(1 * s_{n}) = \int_{0}^{T} 1 \times \sin(\frac{2n\pi x}{T}) dx \\
= \left[ - \frac{T}{2n\pi} \cos(\frac{2n\pi x}{T}) \right]_{0}^{T} \\
= - \frac{T}{2n\pi} \left[ 1 - 1 \right] = 0
}

より 1 * s_{n} = 0 がわかりました。 1 * c_{n} = 0 も同様です。

次に、 s_{n} * c_{k} s_{n} * s_{k} と、 c_{n} * c_{k} ですが、これはオイラーの公式を使うといけそうです( sin cos の積の公式を忘れてしまいました...)。

以下の等式が成立します。(記述が面倒なので、 \omega := \frac{2 \pi}{T} とします。)

 \displaystyle{
e^{i \omega (n+k) x} = e^{i \omega n x} e^{i \omega k x}\\
= (c_{n}(x) + i s_{n}(x))(c_{k}(x) + i s_{k}(x))\\
= c_{n}(x)c_{k}(x) - s_{n}(x)s_{k}(x)\\
\quad + i (s_{n}(x)c_{k}(x) + s_{k}(x)c_{n}(x))
}

一方、

 \displaystyle{
\int_{0}^{T} e^{ i \omega (n + k) x } dx\\
= \int_{0}^{T} c_{n + k}(x) + i s_{n + k}(x) dx\\
= \frac{1}{\omega (n + k)}\left[ s_{n + k}(x) \right]_{0}^{T} + \frac{-i}{\omega (n + k)}\left[ c_{n + k}(x) \right]_{0}^{T}\\
= 0
}

なので、

 \displaystyle{
\int_{0}^{T} c_{n}(x)c_{k}(x) dx = \int_{0}^{T} s_{n}(x)s_{k}(x) dx\\
\int_{0}^{T} s_{n}(x)c_{k}(x) dx = - \int_{0}^{T} s_{k}(x)c_{n}(x) dx\\
}

が成り立ちます。さらに kの符号を変えた、  e^{ i \omega (n - k) x } から、

 \displaystyle{
\int_{0}^{T} c_{n}(x)c_{k}(x) dx + \int_{0}^{T} s_{n}(x)s_{k}(x) dx = 0 \, or \,T (n = k)\\
\int_{0}^{T} s_{n}(x)c_{k}(x) dx - \int_{0}^{T} s_{k}(x)c_{n}(x) dx = 0 \quad
}

よってこれを使うと、

 {\displaystyle s_{n} * c_{k} = \int_{0}^{T} s_{n}(x)c_{k}(x) dx = 0 }

 {\displaystyle s_{n} * s_{n} = \int_{0}^{T} s_{n}(x)s_{n}(x) dx = \frac{T}{2} }

 {\displaystyle s_{n} * s_{k} = \int_{0}^{T} s_{n}(x)s_{k}(x) dx = 0 }

 {\displaystyle c_{n} * c_{n} = \int_{0}^{T} c_{n}(x)c_{n}(x) dx = \frac{T}{2} }

 {\displaystyle c_{n} * c_{k} = \int_{0}^{T} c_{n}(x)c_{k}(x) dx = 0 }

つまり、 1 s_{n}(x) c_{n}(x) は直行することがわかります。

以上のことから、

 \displaystyle{
c + \sum_{n=1}^{\infty} ( a_{n}s_{n}(x) +  b_{n}c_{n}(x) ) = 0
}

に対して、 1 s_{n}(x) c_{n}(x) をそれぞれかけて積分したものを考えれば、

 c = 0 a_{n} = 0 b_{n} = 0 がわかります。

感想

ちょっと元気が無くなってしまい、今回は前半だけです。いろいろ抜けがあると思います、後半の生成系であることを示す方針は全然思いついてないです。ただ関数空間の条件に可積分が必要になりそうですね(多分仮定されてたはず)。

あと、はてなの環境では[tex: ... ]の内部で&が使えないため等式を複数段並べる時とか面倒です。なにか方法があるのでしょうか?

Persistent

Persistentはデータベースアクセスインターフェースを提供するHaskellのパッケージで、DDLDML、などを扱いやすい関数を備えています。

型安全と完結さ、明確な文法という原理に則って開発されていて、PostgreSQLSQLiteMySQL、MongoDBや実験的にRedisもサポートしているそうです。MySQLに関してはjoinをサポートしてい無いそうですが、Esqueletoライブラリによって補完されていると書かれています。また、データベースのマイグレーションも行ってくれるようです。(詳細

データ構造

Persistentはデータベースの構造をどうやってHaskellで表現しているのでしょうか?対応表が載っていたので転記します。

SQL Persistent
Datatypes(VARCHAR, INTEGER, etc) PersistValue
Column PersistField
Table PersistEntity

PersistValueはデータ型、PersistField、PersistEntityは型クラスになっています。

まずは、

Haskell内で記述する必要があるようです。

とりあえず

とりあえずサイトのサンプルを動かしてみます。

{-# LANGUAGE EmptyDataDecls             #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE GADTs                      #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE QuasiQuotes                #-}
{-# LANGUAGE TemplateHaskell            #-}
{-# LANGUAGE TypeFamilies               #-}
import Database.Persist
import Database.Persist.TH
import Database.Persist.Sqlite
import Control.Monad.IO.Class (liftIO)

share [mkPersist sqlSettings, mkSave "entityDefs"] [persistLowerCase|
User
    email    String
    password String
    deriving Show
|]

main :: IO ()
main = runSqlite ":memory:" $ do
    runMigration $ migrate entityDefs $ entityDef (Nothing :: Maybe User)
    hogeId <- insert $ User "hoge@fuga.com" "piyo"
    hoge <- get hogeId
    liftIO $ print hoge

プラグマがよくわかってい無いため、なんとも言えませんが記述する部分はshareの次の行のデータ型定義くらいで済んでるのではないかと思います。もしかしたらリレーションとか考えると複雑になるのかもしれませんが。

感想

途中で力が尽きてしまったので、次はいろいろいじりたい。なんだか中途半端なことが溜まっている気がする。

おまけ:Yesod

YesodはHaskellのWebフレームワークです。Haskellによる、型安全でRESTfulで高性能なWebアプリケーション開発の生産性を向上させる目的を掲げているそうです。

PersistentはYesodに組み込まれているそうです。HaskellのWebフレームワークとしてはかなり有名らしく、githubを見るとすでにバージョンは2.5が出ていました。

pingを知ろう

こんにちは。

シンプルなものって素敵ですよね。自分が好きなものは包丁とまな板です。大工道具もなかなか素敵です。

本当のところはよくわかってないですが、今日はシンプルそうで、使いこなせるとカッコ良さそうな、pingコマンドについてメモしました。(BSD

ping(píŋ)とは?

まずはターミナルからman pingを実行してマニュアルを確認します。

NAME
     ping -- send ICMP ECHO_REQUEST packets to network hosts

ICMPとはInternet Control Message Protocolの略で、IP通信の制御や通信状態の調査などを行なうためのものです。
ECHO_REQUESTとは「エコー要求」と訳されていて、通信可能なら応答するよう要求するICMPのメッセージの一種です。

pingはICMPでネットワークホストにエコー要求パケットを送るコマンド、 つまりネットワークを通して「大丈夫ですか?」と聞くコマンドということみたいです。

オプション

単純にping XXX.XXX.XXX.XXXを実行すると、XXX.XXX.XXX.XXXへパケットが送られ続けます。制御するオプションの一部をメモします。

オプション 内容
-c count count回のパケット送信を行った後停止する
-i wait パケット送信毎にwait秒の間隔(interval?)待機する
-t timeout timeout秒過ぎたら停止する
-W waittime 応答がwaittime秒過ぎたら画面表示しない(最終的には遅れた応答も統計情報として反映はする)

パケットが見たい

-p patternというオプションでは送信するパケットの内容を変更できるようです。 しかしターミナルからはパケットの内容は見えないため(やり方があるのかもしれませんが)、確認できません......
それだとちょっと寂しいので、脱線してOS Xでパケットを見る方法をメモしておきます。

wireshark

ネットワークプロトコル解析ツールのwiresharkを使えばいいようです。オプションなしでhomebrewでインストールするとguiが無いようなので--with-qtをつけてコマンドを打ちます。

brew install wireshark --with-qt

インストールの仕方が悪かったのか、うまく動きませんでしたが、sudo /usr/local/Cellar/wireshark/バージョン/bin/Wiresharkで直接起動したらいけました。

wi-fiを選択して、icmpでフィルタします。あとは試しにping -p ff 外部のIPとして見ると、icmpのrequestとreplyが交互に表示されました。 パケットの中身を見るとffがたくさん並んでいて、-pオプションも効いています!

感想

とりあえずパケットの中身が見れて満足です。これでpingのオプションも少しずつ理解を深めていけそうです。ネットワーク経路なども選択できるようで、その辺りを使いこなしていきたいです。

haskellのパッケージ管理ツールstack

haskellでservantを使いたくて色々調べていたら、サンプルとして上がっているものがことごとくstackというパッケージ管理ツールを想定したものでした。cabal-installの代わりになるものっぽいです。

stackはhaskellプロジェクトの管理を簡単にしてくれるもので、依存関係の解決とか、テスト実行とか、ベンチマーク測定とか色々機能があるようです。あとGHCi起動時のモジュールのロードを勝手にしてくれるみたいです。

というわけでhaskellのパッケージ管理ツールstackを入れてみます。

参考

正直現在の環境をどうやって入れたか覚えてないのですが、確かhomebrewでcabal-installghcをインストールした気がします。それらを全てアンインストールし、

brew install haskell-stack

を実行しました。

GHCiを使うために、

stack setup

を実行。

stack ghci

でGHCiが起動するようになりました。

runghc hoge.hgrunhaskell hoge.hs

stack runghc hoge.hs

で実行できます。

感想

使えるからいいやではなく、何をしているかちゃんと理解しないといけないですね......

vimの移動コマンド

こんにちは。

よく使っているエディタ、vimについてメモします。

vimには便利な移動コマンドが沢山あって魅力的です、でもなかなか使いこなせていない感じがします。上下左右移動を覚えた後、さらに自由にファイルを編集するための移動コマンドを調べてみました。

基本的な移動

コマンド 意味
h 左へ移動
j 下へ移動
k 上へ移動
l 右へ移動
0 行左端へ移動
$ 行右端へ移動
^ 文頭へ移動
g_ 文末へ移動

折り返された行での移動

基本的なコマンドに対してgを頭につけると、折り返し時の移動が楽になります。

コマンド 意味
gj 下へ移動
gk 上へ移動
g0 画面左端へ移動
g$ 画面右端へ移動
gm 画面中央へ移動

例えばgjgkは画面で見たままの上下移動になります。

f:id:ushumpei:20160603014152g:plain

また、g0gmg$コマンドは画面上水平方向の位置へ移動します。

gをつければ画面上で見たままの、上下左右移動、行頭、行末移動になると覚えておくといいと思います。

検索

コマンド 意味
f[char] カーソル位置から行末方向にある[char]の位置にカーソルを移動
t[char] カーソル位置から行末方向にある[char]の直前の位置にカーソルを移動
F[char] カーソル位置から行頭方向にある[char]の位置にカーソルを移動
T[char] カーソル位置から行頭方向にある[char]の直前の位置にカーソルを移動
; 直近のf、t、F、Tをリピートします
, 直近のf、t、F、Tを逆方向にリピートします(つまりfaのあとの,はFa)

f:id:ushumpei:20160603020336g:plain

次の行、次の文、次の段落

コマンド 意味
+ 次の行の最初の文字に移動
- 前の行の最初の文字に移動
) 次の文へ移動(文はドットとスペース.で区切ります)
( 前の文へ移動
} 次の段落へ移動
{ 前の段落へ移動

f:id:ushumpei:20160603015527g:plain

感想

gif作成時にタイプミスしないようにするのが大変でした。(作成にはttygifを使いました。) ...ちょっと再生速度が速いみたいです。

検索で;,を使いこなせば速度が上がるかと思います、,は忘れがちなので気をつけます。

いずれ画面操作系のコマンド(配置、リサイズ等)についてもメモしておきたいです。

コメントアウト一覧

こんにちは。

コメントアウトの構文を覚えられないです。やっているうちにいずれ覚えるだろうと思っていたのですが、全然覚えられていないです。

プログラミングを初めてすぐの頃、cssコメントアウト//と書いて、レビューで指摘された思い出があります。その頃はrailsでプログラミングしていたので、ruby、erb、html、cssjavascriptなどのコメントアウトがごっちゃになっていたみたいです。

そろそろコメントアウトをちゃんと覚えようと思いました。多分随時更新してきますが、とりあえず以下についてメモしておきます。

目次

コメントアウトの構文

Java

class Main {
  public static void main(String[] args) {
  // comment
    System.out.println("hello");

    /*
      comments
      comments
    */
  }
}

戻る

Ruby

# comment
p 'hello'

=begin
  comments
  comments
  (rubocopに`Do not use block comments`と言われました。非推奨なのかな?)
=end

戻る

html

<!-- comment -->
<p>hello</p>

<!--
  comments
  comments
  (コメントアウトの種類は一つですね)
-->

戻る

css

/* comment */
  body:after { content: 'hello' }

/*
  comments
  comments
  (これもコメントアウトの種類は一つ)
*/

戻る

javascript

  // comment
  alert('hello');

  /*
    comments
    comments
    (Javaと同じと覚えればいいかも)
  */

戻る

haskell

-- comment
main = putStrLn "hello"

{-
  comments
  comments
  (この複数コメントの記法のルーツはなんだろう?)
-}

戻る

mysql

-- comment
#  comment(この構文はpostgresqlにはないみたいです)

select "hello";

/*
  comments
  comments
*/

戻る

bash

# comment
echo "hello"

<< EOS
  comments
  comments
EOS

戻る

Markdown

<!-- comment -->
**hello**

<!--
  comments
  comments
  (htmlと一緒です)
-->

戻る

感想

内容と全然関係ありませんが、Markdownでのページ内リンクの貼り方を覚えました。

<a name="target"></a>ここに飛ぶ

[ここを押すと](#target)

という具合です。

とりあえず多分コメントアウト覚えました。

データ型と型クラスの違い

「すごいHaskellたのしく学ぼう!」を勉強した時に、データ型と型クラスで混乱してしまったので、メモ書いておきます。

ザックリまとめると、こんな感じです。

  • データ型:データ構造を定義するもの
  • 型クラス:振る舞いを定義するもの

ちゃんとした内容は「すごいHaskellたのしく学ぼう!」の7章に書いてあります。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

以下簡単な例と概要を書いていきます。

データ型(data)

データ型の例としては、IntWordIntegerFloatDoubleCharBoolOrdering[]()Maybeなどがあります。

データ型の扱いは他のプログラミング言語におけるデータ型と大体同じかと思います。ただし、定義には2種類のコンストラクタと呼ばれるものが出てくるので注意しなければいけません。

値コンストラクタ(Data Constructor)

値コンストラクタはデータ型の値を作成するために使用する関数です。データ型の定義において等号の右側に記述されます。例を見てみます。

data Foo = Bar Int | Baz Float | Qux Int Float

データ型Fooの値コンストラクタはBarBazQuxです。例えばBar値コンストラクタにIntデータ型の値を渡すことでFooデータ型の値を作ることができます。

ghci>let bar = Bar 1
ghci>:t bar
bar :: Foo

つまりBar

Bar :: Int -> Foo

という関数になっています。

違う例でいくと、基本的なデータ型BoolではFalseTrueという値コンストラクタを持ちます。

data Bool = False | True

FalseTrueを定数と考えるか、引数0の値コンストラクタ関数と考えるかは自由ですが、僕は引数0の値コンストラクタと考える方がデータ型の定義が一般化できるので好きです。

型コンストラクタ(Type Constructor)

型コンストラクタはデータ型を変数にとり新たなデータ型を定義します。テータ型の定義では等号の左側に現れます。例をもとに見ていきましょう。

data Maybe a = Nothing | Just a

Maybeデータ型の等号の右側には、二つの値コンストラクタ(引数0、引数1)が並んでいます。ところがJustコンストラクタは引数のデータ型がaとなっていて、こんなデータ型ないよ、と思うわけです。

一方等号の左側にはMaybe aという表記が見えます。このMaybeの部分が型コンストラクタです。この型コンストラクタは色々なデータ型aに対し、いろいろなデータ型Maybe aを作ることができると言っています。

実際に使ってみます。

ghci>let maybe_char = Just 'c'
ghci>:t maybe_char
maybe_char :: Maybe Char

ここではJust値コンストラクタにCharデータ型の'c'を渡すことで、Maybe Charデータ型の値maybe_charを作っています。

Javaで配列の定義でint[]String[]と書いたことや、総称型のワイルドカードの概念にやや似ていますね。

Maybe自体に直接データ型を指定してデータ型を得ることは関数定義の時などですが、型推論に頼ってばかりの僕にはあまり関係ないみたいです。

ちなみにGHCiでは:tに続けて型名を入力すれば型の情報を教えてくれます。定義、インスタンスなどを確認したい場合は:iが便利で結構万能です。

型クラス(type class)

型クラスは、データ型に実装されたり、違う型クラスに継承されたりします。型クラスの例としては、NumEnumShowReadFunctorApplicativeMonad...などたくさんあります。

型クラスはある性質を一般化したものだと考えられます。例えばNumは整数、浮動小数などの「数」という概念が持つべき振る舞いを定義していますし、Enumは列挙するという振る舞いを定義しています。

データ型には複数の型クラスを実装させることができます。継承も複数可能です。自由です。今回は大変なので継承は扱わず実装のみ見ていくことにします。

型クラスの定義はclassによって宣言します。

class Hoge a where
  fuga :: a -> Int

この型クラスを実装したいデータ型Piyoは、関数fugaを実装しなければいけません。実装はinstanceで宣言します。

instance Hoge Piyo where
  fuga Piyo = 0

(例がとても酷くて申し訳ないです...)

例が例なのに具体的ではなかったので、具体的に初期状態でインポートされているNum型クラスを見てみましょう。

ghci>:i Num
class Num a where
  (+) :: a -> a -> a
  (-) :: a -> a -> a
  (*) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInteger :: Integer -> a

僕がよくデータ型だと間違えてしまうのがこのNumです。これはIntWordFloatDoubleなどの数値系のデータ型がもつ、足す、引く、かけるといった、数としての振る舞いを定義しています。(ちなみにnegateは符号の反転、signumは符号を返しそうです、実際Intではそのような実装が与えられます)

これに対しIntは以下のような実装を与えています。参考

instance  Num Int  where
    I# x + I# y = I# (x +# y)
    I# x - I# y = I# (x -# y)
    negate (I# x) = I# (negateInt# x)
    I# x * I# y = I# (x *# y)
    abs n  = if n `geInt` 0 then n else negate n

    signum n | n `ltInt` 0 = negate 1
             | n `eqInt` 0 = 0
             | otherwise   = 1

    {-# INLINE fromInteger #-}   -- Just to be sure!
    fromInteger i = I# (integerToInt i)

...ちょっとよくわかりません。#はmagic hashと呼ばれるものらしく、後置修飾子として変数に#を付与できるようにするものみたいです(参考)。I#GHC.Types.I#のことで、おそらくこの中で定義した和や差の処理を実装として与えているのだと思います。

感想

良い例が全然出せず残念でした。申し訳ないです。

収穫としてはghcglasgow haskell compilerの略だと知ったことです。

あとこれだけ書いたらもう、データ型と型クラスをごっちゃにすることはなさそうです。

はじめて

はじめまして。

僕は会社員でWebプログラマーをやっています。

何かアウトプットしないとまずいかなと思い、まずはブログをはじめてみました。

このブログには生活で気になったことを随時調べて書いていくので、結構雑多な内容になるかと思います。内容もざっくりした理解を書いていく予定です。

第一歩としては、自身の備忘録として、役に立つものになればいいでしょう!