purescript-conveyorにLogger実装足しといた
追記
本記事のパッケージは現在メンテされておりません。
サーバー向けパッケージは再実装されたものがこちらにあります。
あくまでデフォルト実装としての簡易的なLoggerです。
基本的にはこの実装を参考にして、みなさんのお好きなLoggerをつくってServableにしてくださいということでひとつ。
椅子を高級品にした
いきさつ
ある日、自宅作業中に背もたれによっかかったら、小さく「ミシッミシミシミシ」と音を立てていたのだが、その瞬間はあまり気にしていなかった。 そのまましばらくよっかかっていると、どうも少しずつ背もたれが倒れていっているようなので、これはおかしいと思い、椅子をよく見てみると、 背もたれの留め具の部分が完全に破損して飛び出ていた。床をみると破片がめっちゃ落ちていた。 サンワサプライのやっすい椅子を使っていたのだが、私は体格がいいほう(178cm 90kg弱)なので私の体重に耐えきることができなかったっぽい。 たぶん2年くらいしかつかっていない。
そういうわけで、私もフリーランスになったため、そろそろ良い椅子を買おう、ということにしました。
何買うか
実は以前の職場でコンテッサを使っていて結構よかった記憶があるのでコンテッサが第一候補ではあったが、せっかくなので調査と視座をすることにした。
事前調査としては、椅子の基本方針として、「前傾」をサポートするか「後傾」をサポートするかというのがあり、そこがわりと大きな違いにはなりそうな感じであった。 また、ハーマンミラー製品は他のメーカーと比べて大きな違いがあり、他のメーカーよりも保証の条件が厳しい代わりに、保証期間が12年でとても長いということもこのタイミングで知った。
試座
試座は自分の普段のデスクワーク時の姿勢の変化やスタイルを意識してやると良いという事でそういう感じでやった。
近場を何店舗か回りながら視座してみたが、私はちょっと困っていた。 というのも、ぶっちゃけ数分程度の試座だと、高級なオフィスチェアは、どれもとても座り心地がよく、どれがいいという感じにならなかったのである。これは以前の職場で椅子を選ぶときに全く同じ感想があったのを思い出した。
私は作業中かなり前傾姿勢になるので前傾チルトは絶対にほしいのでそれがついていることと、保証が12年ということでハーマンミラーの製品にするかーという感じで決めた。
結局何買ったのか
相当悩んだが、結局セラチェアを買った。 セラチェア - オフィスチェア - ハーマンミラー
実は、今回椅子を買うときにひどいギャンブルをしてしまっていて、ハーマンミラー製品のうち、このセラチェアだけは全く座ったことがない。 この椅子は置いてあるところが少ないのだ。
なぜ、そんな頭の悪いことをしてしまったかというと、高けりゃだいたいある程度満足感があることは試座でわかっていたのもあるが、 とてもほしくなってしまったからなのだ...。
買う前に何がそんなに気に入ったかというと、
- 布を使っていないので汚れにつよく、ヘタリに対しても特にかなり強そうだったこと
- できることならノーメンテで長く使いたいから
- メッシュすらないとか、唯一無二感あって、めっちゃかっこいいなこれって感じだったこと
- 私はこういう感じの製品をめっちゃかっこいいと思ってしまうタイプ
こんな感じでビビッときてしまった。
ほんで、地味に調整機能は高機能で必要な調整機能は全て揃っていたこと、体格のいい人間にはかなりマッチする(らしい)というインターネットの情報から、「まぁ座ってないけど買っちゃお!えい!!!!!!!」って感じで買っちゃった感じです。
ただし、調査では、「座面が硬く感じる、冷たく感じる」という意見もあり、正直到着するまでビクビクしていた。
届いてから
到着時はとてもでかいダンボールに入って届けられるので、家に入らず、廊下で開封作業を行った。
んで、実際使ってみての感想だが、丸1日座っているがかなり最高で、座面の件も硬くないし、(たぶん暖房つけてるからだけど)冷たくもない。 クッションもないのに、不思議とケツも痛くならない。私はこの椅子にマッチするタイプだったらしい。これはセラチェア独自のセルラーサスペンションとかいう仕組みによるものっぽい。
ギャンブルに勝った。買ってよかった。
PureScriptで静的ファイル配信できるパッケージ書いた
追記
本記事のパッケージは現在メンテされておりません。
サーバー向けパッケージは再実装されたものがこちらにあります。
はじめに
静的ファイルを配信するときはとりあえずnginxなどにお任せすればいいかと思いつつも、 昨今ではTwelve-Factor Appの考え方もあり、静的ファイルの配信もアプリケーションサーバーでしようということで、 PureScriptで静的ファイル配信するパッケージを書きました。
本番ではCDNのオリジンとして動いてもらうという感じにはなると思います。
どんなやつ?
リポジトリはGitHub - oreshinya/purescript-static-serve: Serve static filesです。
ランタイムはnodejs想定です。
とりあえず最低限ということで、雑に言うと以下の3つのみ対応しています。
- 静的ファイル配信
- maxageの設定
- 条件付きGETの対象については、
Last-Modified
のみ対応しておりETag
は対応していません。
使い方
module Main where import Prelude import Control.Monad.Eff (Eff) import Data.JSDate (LOCALE) import Data.Maybe (Maybe(..)) import Node.FS (FS) import Node.HTTP (HTTP, ListenOptions, createServer, listen) import StaticServe (staticHandler) config :: ListenOptions config = { hostname: "0.0.0.0" , port: 3000 , backlog: Nothing } main :: forall e. Eff (fs :: FS, http :: HTTP, locale :: LOCALE | e) Unit main = do server <- createServer $ staticHandler { root: "./public", maxAge: 60 } listen server config $ pure unit
現段階では、設定としては、rootディレクトリの設定とmaxageの設定のみです。
この例だとpublic以下に置いたファイルが配信されるようになります。
さいごに
やったぁPureScriptで静的ファイル配信できるようになったぁ(小並感)
(このパッケージがエッジケースに対応できているかは微妙な感じです。)
追記
最近仮想通貨買いはじめた
年末に初めて仮想通貨を購入した。 アーリーアダプターではないが、夢のある感じで楽しい。
チャート漁り、情報漁り、草コイン漁りがめっちゃ楽しい。
明らかにバブルという感じで、我々の上の世代はこんな楽しいことを経験していたのかという感覚がある。
通貨を購入した瞬間に金を捨てたと自己暗示しまくって買っていると、短期的な値下がりが気にならないタイプなので楽しめているのかもしれない。
今年は余剰資金が増える予定なので、いろいろ買っていきたい。
PureScriptの末尾再帰最適化
はじめに
年が明けてますが、PureScript Advent Calendar 2017 - Qiitaの19日目の記事にしてしまいます。
PureScriptは末尾再帰最適化ありますが、モナディックな再帰は最適化されません。 よって、何も考えないと稀に、コールスタックに積み上がりすぎてエラーが起こるという状況に遭遇するかもしれません。 というか私は遭遇しました。 そんなときのためのパッケージを紹介します。
紹介
- GitHub - purescript/purescript-tailrec: A type class which captures stack-safe monadic tail recursion
- GitHub - paf31/purescript-safely: A combinator for making any monadic control operator stack-safe
後者はtailrecをラップしたパッケージです。
これらを使って書き直すと、きっとエラーが起こらなくなるはずです。
さいごに
サンプルコード書こうかと思ったけど、まぁREADME読めばわかるしええやろ、という気持ちで手抜きの記事となりました。
purescript-conveyorにBatch operationの機能を足した
追記
本記事のパッケージは現在メンテされておりません。
サーバー向けパッケージは再実装されたものがこちらにあります。
はじめに
年が明けてますが、PureScript Advent Calendar 2017 - Qiitaの21日目の記事にしてしまいます。
前回、PureScriptでAPIサーバー用のパッケージつくってみた - oreshinyaのブログというようなAPIフレームワークをつくったことを記事にしましたが、 このフレームワークにBatch opearationの機能を足しました。 また、その際に全面的にソースコードを書き直したため、変更点を書きます。
Batch operationってなに
複数のエンドポイントを1回のリクエストで実行する機能です。
複雑なアプリケーションになると、ひとつの画面に必要なデータが非常に多岐に渡ります。 そのような状況下の中、ひとつのAPIで色々な多くのデータを返すか、単機能なAPIを複数回叩くかという選択をすることを最初に考えるかと思います。 このことに対して、何も対策的な仕組みを入れない場合、前者の場合はUIによりすぎたメンテのしにくいAPIによっていくし、後者は何度もリクエスト往復するのでとても時間がかかります。
こういったことに対して、数年前からBFFという概念が公に出るようになりました。 ただ、気合の入ったBFFをしなくても、単純なbatch operationだけでもあると、経験上、わりと快適になるため、自分で使うためのライトユースとして、この機能を足しました。
Servable
のメンバの型が変わった
変更コミットたちです。
Batch operationを入れるために、Servable
のメンバの型を変えました。
以前の型はserve :: c -> s -> Request -> Response -> String -> Maybe (Eff (http :: HTTP | e) Unit)
で、新しい型はserve :: s -> c -> RawData -> Aff e Responder
になります。
大きな変更点は、返り値の型となります。
以前の型では、serve
の実行文脈の中でレスポンスをクライアントに返すことを期待した型付けでしたが、新しい型では、serve
の文脈でレスポンスとなるデータをつくって返すだけになっています。
新しい型にしたことによって、batch operationの実装は、serve
を指定された各エンドポイントのパラメータの配列を用いて、traverse
して複数のレスポンスをまとめればいいだけになりました。
その他の変更
- Request bodyのdecodeに関しては、purescript-simple-jsonに依存するように変更して、
Readable
型クラスを削除した Respondable
型クラスの全面的な書き直しHandler
を削除して、普通にAff
で動くように変更した- 関数の引数の順番とか数とか引数そのものを地味に変えた
- まぁ、なんか色々書き直した
まだ改善できるところはある
現状は、各エンドポイントを順番に処理してるだけなので、concurrentに実行できるようにするとよりよさそうです。
使い方
Servable
のインスタンスをBatch
型で包んで初期化すれば、OKです。
リポジトリのサンプルコードとほぼコピペですが、以下のような感じで初期化します。
runWithContext config 777 $ Batch { contextTest, errorTest, rawDataTest, createBlog }
以下のようなデータをrequestのbodyとして、POST /batch
におくりつけると、
[ {"path": "errorTest"}, {"path": "contextTest"}, {"path": "createBlog", "body": { "title": "hoge", "content": "うんち in batch" }}, {"path": "rawDataTest", "body": "ろーでーた"} ]
以下のようにかえってきます。
[ { "contentType": "application/json", "code": 500, "body": { "messages": [ "Internal server error ;)" ] } }, { "contentType": "application/json", "code": 200, "body": { "yours": "777" } }, { "contentType": "application/json", "code": 200, "body": { "fuck": "title: hoge, content: うんち in batch requested." } }, { "contentType": "application/json", "code": 200, "body": { "yours": "\"ろーでーた\"" } } ]
単純パーセプトロンを実装してみた
年が明けていますが、PureScript Advent Calendar 2017 - Qiitaの20日目の記事にしてしまいます。
Python機械学習プログラミングを2章まで読んだ。
読んだ内容を体にいれるために、適当にPureScriptで単純パーセプトロンを実装してみる。
module Main where import Prelude import Control.Monad.Eff (Eff) import Control.Monad.Eff.Console (CONSOLE, log) import Control.Monad.State (StateT, execStateT, get, modify, put) import Control.Safely (replicateM_) import Data.Array (snoc, zipWith) import Data.Foldable (sum) import Data.Traversable (for) import Data.Tuple (Tuple(..)) -- 学習によって更新されていく値 type State = { weights :: Array Number , bias :: Number , errors :: Array Number } main :: forall e. Eff (console :: CONSOLE | e) Unit main = do -- 学習率は0.01とし、エポック数は10としてみる state <- flip execStateT initialState $ fit 0.01 10 log $ "expected: 1.0, gotten: " <> (show $ predict $ netInput [1.0, 1.0] state) log $ "expected: -1.0, gotten: " <> (show $ predict $ netInput [0.0, 1.0] state) log $ "expected: -1.0, gotten: " <> (show $ predict $ netInput [1.0, 0.0] state) log $ "expected: -1.0, gotten: " <> (show $ predict $ netInput [0.0, 0.0] state) log $ "weights: " <> show state.weights log $ "bias: " <> show state.bias log $ "errors: " <> show state.errors -- 学習 fit :: forall e. Number -> Int -> StateT State (Eff e) Unit fit eta iter = replicateM_ iter do errors <- for samples \(Tuple xs y) -> do st <- get let d = eta * (y - predict (netInput xs st)) put $ st { weights = zipWith (+) st.weights $ map ((*) d) xs , bias = st.bias + d } pure d -- イテレーションごとに雑に誤差をいれておく modify \s -> s { errors = snoc s.errors $ sum errors } -- ステップ関数 predict :: Number -> Number predict z = if z >= 0.0 then 1.0 else -1.0 -- 総入力 netInput :: Array Number -> State -> Number netInput xs { weights, bias } = bias + (sum $ zipWith (*) xs weights) -- 初期状態 initialState :: State initialState = { weights: [ 0.0, 0.0 ] , bias: 0.0 , errors: [] } -- サンプル -- 特徴量と期待する出力 samples :: Array (Tuple (Array Number) Number) samples = [ Tuple [ 0.0, 0.0 ] (-1.0) , Tuple [ 0.0, 1.0 ] (-1.0) , Tuple [ 1.0, 0.0 ] (-1.0) , Tuple [ 1.0, 1.0 ] 1.0 ]
今回はAND演算を学習させてみた。
実行してみる。
expected: 1.0, gotten: 1.0 expected: -1.0, gotten: -1.0 expected: -1.0, gotten: -1.0 expected: -1.0, gotten: -1.0 weights: [0.04,0.02] bias: -0.06 errors: [0.0,-0.02,-0.02,0.0,-0.02,0.0,0.0,0.0,0.0,0.0]
6回目から誤差が出なくなっているっぽい。
ADALINEも実装しようと思ったが、飽きたので一旦終了。