本日はこれの他に、cabal replの件については依存しているcabal-installを更新したりしました
https://twitter.com/igrep/status/1601862213442359297
https://twitter.com/igrep/status/1601862213442359297
Rem m の (^) :: (Num (Rem m), Integral a) => Rem m -> a -> Rem m (ただし instance Data.Reflection.Reifies m Word => Num (Rem m)) を黒魔術で高速化すべく頑張りますRem m の (^) が遅かったのです.profをとっていないのでよくわからないのですが, この原因は, Data.Reflection.reflect :: Data.Reflection.Reifies m a => proxy m -> a で出てくる reflect :: Reifies m Word => proxy m -> Word の素性が simplifier にから見てよくわからないので,インライン化もされない (*) :: Rem m -> Rem m -> Rem m の呼び出しが何度も reflect を呼んで最適化もされない,ということだったっぽいです.そこで, reflect を (^) の計算の最初だけ呼び,`(^)` の実装内部においては, (*) のかわりに,その実装に使われている modulus つき乗法関数(自作) unsafeModMult :: Word -> Word -> Word -> Word を呼ぶようにする,ということをしたいです.ところが,RULES で (^) を書き換えようとすると type checker が Num (Rem m) を知ってるくせに Reifies m Word を知らない,という事態が生じます. そこで Num (Rem m) だけの制約からmodulusを取ってくる必要に迫られるのですが,`fromInteger :: Integer -> Rem m` が remFromIntegerWithMod modulus に書き換えられるように実装されていることを利用して RULES で computeModulusFromNumConstraint (remFromIntegerWithMod modulus) = modulus と書き換える,みたいな真似をしています. これで, AtCoder ABC282-E の実行速度が https://atcoder.jp/contests/abc282/submissions/37366230 (788ms) から https://atcoder.jp/contests/abc282/submissions/37872422 (173ms) へと高速化しました.手書きの剰余冪乗を用いた