IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

hs-bootファイルとは何か

Haskellのライブラリのコードを見ていると、まれに、hs-bootという拡張子がついたファイルを見かけることがあります。なんだろうと思っていたのですが、モジュールインポートで相互参照を解決するために使用するようです。

10.8. Filenames and separate compilation — Glasgow Haskell Compiler 8.6.5 User's Guide

Haskell - resolving cyclical module dependency - Stack Overflow

モジュールの相互参照 - Qiita

比(ratio)、割合(proportion)、率(rate)をきちんと区別する

英語 定義 補足
ratio 分子分母が別々なもので、互いに相手を含まない 一般には次元がある BMI 性比
割合 proportion 分子が分母に含まれる分数 次元はない 値はゼロから1の間 有病率 打率 死亡率 「率」と言うが、意味は「割合」であることに注意
rate 現象が起きる速さを測る 平均的な率とは、時間当たりで平均すること 離婚率 反応速度 気温の逓減率 率の意味で正しく死亡率を使うこともある。

「医療統計を学ぶ」の1章に説明があります。

宇宙怪人しまりす 医療統計を学ぶ 検定の巻 (岩波科学ライブラリー)

宇宙怪人しまりす 医療統計を学ぶ 検定の巻 (岩波科学ライブラリー)

比(ratio)、割合(proportion)、率(rate)をきちんと区別する

英語 定義 補足
ratio 分子分母が別々なもので、互いに相手を含まない 一般には次元がある BMI 性比
割合 proportion 分子が分母に含まれる分数 次元はない 値はゼロから1の間 有病率 打率 死亡率 「率」と言うが、意味は「割合」であることに注意
rate 現象が起きる速さを測る 平均的な率とは、時間当たりで平均すること 離婚率 反応速度 気温の逓減率 率の意味で正しく死亡率を使うこともある。

「医療統計を学ぶ」の1章に説明があります。

宇宙怪人しまりす 医療統計を学ぶ 検定の巻 (岩波科学ライブラリー)

宇宙怪人しまりす 医療統計を学ぶ 検定の巻 (岩波科学ライブラリー)

ghciを使ってざっくり性能測定

カジュアルにghci上で性能測定をしようと思ったのですが、少し工夫が必要なようです。

ghciでは:set +sすることで性能を測ることができます。。

Haskell function execution time - Stack Overflow

ghci上での計測なので、表示する処理も計測に含まれしまいます。

Prelude> replicate 9999 1
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
途中省略
,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
(0.42 secs, 35,127,944 bytes)

表示する処理自体は除いて計測をしたいのですが、ghci上で表示させないことはできないようです。(そもそも、interactiveに処理結果を見ながら実行していくためのだからと思います。)

https://stackoverflow.com/questions/32926805/disable-printing-of-io-results-in-ghci

表示結果を無理やり無視すると、そもそも計測したい処理が、遅延評価のため、実行されません。

Prelude> (\x -> return ()) $ replicate 9999 1
(0.00 secs, 92,352 bytes)

強制的に評価をさせるために、deepseqパッケージを使います。

deepseq: Deep evaluation of data structures

Prelude> import Control.DeepSeq
(0.00 secs, 0 bytes)
Prelude Control.DeepSeq> deepseq (replicate 9999 1) (return ())
(0.13 secs, 648,528 bytes)

これで、おおよそ、評価したい処理の性能を見ることができる(はず)。

実際に性能を比較したかった処理は、リストを2つに分割する実装でした。型としては[a] -> ([a], [a])です。

一つはlengthを使って2つに分割します。これは、コード上リストを2回走査することになります。

Prelude Control.DeepSeq> splitHalf' xs = splitAt (length xs `div` 2) xs
(0.00 secs, 0 bytes)

もう一つは、リストの走査を1回で行う実装です。

Prelude Control.DeepSeq> first f (a,b) = (f a, b)
(0.00 secs, 0 bytes)
Prelude Control.DeepSeq> :{
Prelude Control.DeepSeq| 
Prelude Control.DeepSeq| splitHalf :: [a] -> ([a],[a])
Prelude Control.DeepSeq| splitHalf xs = go xs xs
Prelude Control.DeepSeq|   where
Prelude Control.DeepSeq|     go (y:ys) (_:_:zs) = first (y:) (go ys zs)
Prelude Control.DeepSeq|     go ys _ = ([],ys)
Prelude Control.DeepSeq| :}
(0.01 secs, 0 bytes)

2つを比較すると、1回の走査のほうが処理が速いと思ったのですが、結果は逆でした。

Prelude Control.DeepSeq> deepseq (splitHalf'  $ replicate 9999999 'a') (return ())
(1.58 secs, 1,200,091,064 bytes)
Prelude Control.DeepSeq> deepseq (splitHalf  $ replicate 9999999 'a') (return ())
(7.39 secs, 1,732,534,400 bytes)

Firefoxのアドオンを作ってみた

あらかじめユーザ登録をして、ログインをしておく。

f:id:naotoogawa:20190520224420g:plain
登録サイト

Submit Your First Add-onを選択

f:id:naotoogawa:20190520224501g:plain
配布方法の選択

Firefox Add-onsに登録するのでOn this siteを選択しContinueを選択、次の画面で、Select a fileを選択し、作成したAdd-onをアップロードする。

f:id:naotoogawa:20190520224520g:plain
検証エラー

See full validation reportのリンクを選択すると、エラーの内容がわかる。

f:id:naotoogawa:20190520224533g:plain
エラー詳細のページ

エラーを確認し、修正し、再度アップロードする。

f:id:naotoogawa:20190520224554g:plain
検証に成功

コードを難読化などをしていると、ソースコードの提出が求められる。

f:id:naotoogawa:20190520224605g:plain
ソースコード要求の確認

今回はAdd-onのコードは素のJavaScriptなので、Noを選択して、Continueを選択し、次の画面で、Add-onの説明文を登録する。

f:id:naotoogawa:20190520224617g:plain
説明文の登録

しばらくすると、登録される。

f:id:naotoogawa:20190521214247g:plain
登録完了

Add-onを更新する手順は、新規登録と同じ。

f:id:naotoogawa:20190520224656g:plain
更新失敗した場合

履歴が確認できる。

f:id:naotoogawa:20190520224710g:plain
更新成功