haskell-jp / random #10

最近社内Slackで江添さんのhaskellに纏わる誤解を説くbot化しています
Haskell.orgが2年ぶり?にGoogle Summer of Codeにメンター組織として採択されました。

https://summerofcode.withgoogle.com/organizations/5706672807346176/
本当に素朴なトピックっぽくなるのですが、LTSのソルバを更新して一式環境を新しくしたら、Hlint が ++ でなく <> でリスト結合しないの? っていうサジェストをしなくなりましたね
hlint は、バージョンによって言うことがコロコロ変わりますよ。
そうだったのか……
すばらしい!まとめて記事にしていただきたいぐらいです! :yum:
あと、<> が semigroup のメソッドになって、GHC 8.4 から semigroup パッケージが base に組み込まれます。現在、<> 周りは変化が激しいです。
なので、ちょっと気になって調べたのですが、そもそも https://hackage.haskell.org/package/base-4.10.1.0/docs/src/GHC.Base.html#local-6989586621679017803[a] に対する mappend の実装が
{-# INLINE mappend #-}
        mappend = (++)

ってなってて、思いっきり自分でたらい回しの順序を増やしているだけだった…
デフォルトの実装もなくなったので、面倒でも実装を書いておくのが正しい対策のようです。
別のプログラミング言語の + で文字列結合するよりビルダー経由で… っていうノウハウが逆転してしまうアレを連想してしまった(普通に [a] に対しては ++ でよいっぽい)
江添さん、なんだかんだで「わかり」を得ると途端に絶賛しだす
いちいち ++import Data.Monoid (<>) して書き換える必要なんてなかったんや…(つらい)
遅延評価されるリストですしね。 :smirk:
実際のところ、文字列に関しては
https://hackage.haskell.org/package/text-1.2.3.0/docs/Data-Text-Lazy-Builder.html
https://hackage.haskell.org/package/bytestring-0.10.8.2/docs/Data-ByteString-Builder.html
など、文字単位で1個ずつ結合していく ++ よりも効率のよいビルダーがあるので、参考までに。(すでにご存じでしたら済みません)
参考:
最終的にputStrLn程度に出力する、つまりは Show a 実装程度には ++ として、大規模にファイルとして出力する、あるいは pretty-print するとか AST みたいなデータ構造の場合にはビルダー使うっていうやり方してますねー
map より fmap の方がいいんじゃね?とも言われるし、てっきり多相関数の方がコンテナ型を変えたとき( [a] から Vector a に変えるとか)に楽だから言ってるのかと思ってた。
ああ! map じゃなくて <$> つかいなよ も前のHlintにありましたね。
しかし…
instance Functor [] where
    {-# INLINE fmap #-}
    fmap = map
こういうの、もちろん haskell の言語仕様ではなく GHC の実装であるから、もしかしたら処理系によっては何故か抽象的な方の関数の方が効率の良いパターンがあるかもしれないけれど、そもGHC拡張つかったファイルの時点でGHCに寄った実装でいいんや…
将来型を変える気がないのであれば、素朴に専用の関数を使うのでいいです。メソッドを使う必要はありません。
Prelude の関数実装は一度ならずふとしたきっかけごとに見直すと学びがありますね…
いやまぁ、きっかけは code-review のところで ++ つかってる箇所についてそう指摘しようかと思ったら、そういえばホントに <> 使った方が効率いいんだっけか? ってなったからでした
<> で繋ぐようにコーディングする場合、意志的に左右の変数がそれこそ [a] でなく、ビルダーに置き換えたり newtype などで敢えて別のコンテナにした型として取り扱う予定があるとかになるでしょうね。 <$> についても同様(しかし、それだったらその必要なタイミングで書き直すので十分)
Haskell に IntelliJ IDEA なみのIDEができれば、そういう書き換えも一瞬でできるんでしょうけどねぇ... :disappointed_relieved:
haskell-tools-refactorに期待か?
https://www.reddit.com/r/haskell/comments/3sm1j1/how_to_mix_the_base_functorrecursion_scheme_stuff/
自分でGADTsスタイルのASTFunctor書いてみてやっとインデックス付きFixのモチベーションが理解できてきた
@igrep ふと思いついてまだ深く考えてないんですが技術書典での自分と @y_taka_23 さんの卓で Haskell.jp の宣伝をするポストカードみたいなもの配りませんか?
いいですね!誰か知り合いを手伝いに行こうと思っていたので、更によい口実ができました! :smile:
https://trello.com/b/GfAyczPt/haskell-jp
に追加しましょう!
最初からTODOで大丈夫です。
期限ややることなどを挙げておいていただけると助かります! :pray:
見てる限りだとみなさん結構hlint使ってらっしゃるんですね
前に使ってた時にうるせぇわざとこう書いてんだよっていいたくなる指摘ばっかりだったので使うのをやめてしまった…
うるさいルールは、--ignore で消せばよいかと。
hlint --ignore="Use fewer imports" --ignore="Use camelCase" とか
了解です!
何も考えずhlintに矯正されてしまった
いっそ自動で直してもらいたい、すでにあるのかもしれませんが
迷惑メール判定されてたという初歩的なあれでした orz
コーディングスタイルは一貫したいしlintも機械がやってほしいっていう需要はあって。やっぱりみんな gofmt みたいなのを求めてしまうのです https://hackage.haskell.org/package/hfmt
Suggestion: Reduce duplicationはコピペに対する抑止力になるので重宝してるんですが、ただfactor outしたところで「これにどんな名前をつければいいんだろ」みたいなコード片が出来上がることもあるので、うーんという感じです
3日前に PR 投げたけど音沙汰がない……
メンテする気ないかな https://github.com/projectorhq/haskell-liquid/pulls
一週間ぐらいたったら ping を打つとよいです。
こんな状況でも、くじけてはダメ。
3日ぐらいならよくありますよ。
ただ、ちょっと気になったんですが、
部外者ながら指摘しますと、
https://github.com/projectorhq/haskell-liquid/pull/6/files#diff-2d0936a8864887eabbf384ad52ad12da
の修正前のとおり、テストでわざわざ「空文字列の場合は失敗とする」と明記しているのにそれを修正すると言うことは、それなりの動機を description などに書いた方がいいんじゃないかと思います。
その方が説得力があるかと。
自分の利用には困らないので気長に待ってみます
空文字列の件は確かに 動機足しておこう
AstをFunctorとして、Fixコンビネータと組み合わせてめっちゃ柔軟に取り回せるところまでは良かったんですが、Ast -> Env -> Val の Val の型構成子に「組み込み関数およびユーザー定義関数」の実態が入る為に Functor に出来ないってところで詰まりました
[a] -> Either e a って関数の型をFunctorにする術ってあるのだろうか…
ちょっとあまりやりたいことがよく分かってませんが,negative positionがなんらかのfunctorであるのを保ったままということなら,多分無理だと思いますね.
https://hackage.haskell.org/package/bifunctors-5.5/docs/Data-Bifunctor-Biff.html#t:Biff において pがProfならBiff p f gはどうしてもProfになってしまうので
newtype Foo e a = Foo([a] -> Either e a) したときに fmap :: (a -> b) -> Foo e a -> Foo e b と考えてやると何らかの方法で [b] -> Either e b な関数を作る必要がありますが、 [b][a] に変換して [a] -> Either e a に渡す方法が無いので無理な気がします(圏論わからないけど多分mizunashi様の言っていることと同じ)