haskell-jp / questions #16

@tyvutt has joined the channel
machinecell について質問です。
https://hackage.haskell.org/package/machinecell

複数のストリームが同時に流れることがあると思うのですが、その場合、複数スレッドで並行(?)処理されるような機能はありますでしょうか?
readme に parallel という文字が見えるのですが、それがどういう意味なのかいまいちつかめず・・・
どうもです。そこのparallelという単語は、単にArrowの (***) 演算子が平行に射を合成するよ、という意味で使っているもので、並列演算の意味ではないんですね。パッケージの標準機能としては、マルチスレッド的なものは提供していません。
並行処理対応としては、Pipes.Concurrentのspawnに相当する機能を試験実装していたりします(今作っているアプリのコードにこっそり入っている)。 https://github.com/as-capabl/armageddon/blob/53004f980f17eea5c6ea38a8c5ea53d2ead264e9/machinecell-extra/src/Control/Arrow/Machine/World.hs#L487
あ、作者さんだ!
回答ありがとうございます!
マルチスレッド的な事情については了解しました。
試験実装の方、おもしろそうですね!
とりあえずコンパイルが通るコードが無いと何をしたいのかわからない
引数を([Bool], Int) -> xにするぐらいなら[Bool] -> Int -> xにした方が良さそうですが
そもそもこの[Bool]必要なのか疑問
Slack上の「Haskell入門 関数型プログラミング言語の基礎と実践」読書会で
「transformersパッケージと mtlパッケージの違いはなんだろう」
という疑問が出てました。
https://umekitahs.slack.com/
transformers と mtl の歴史的なことは https://wiki.haskell.org/Monad_Transformer_Library にまとまっているようです。これは私のブログ () にも書いたことがあり、孫引きしてしまうと、

まず初期にmtl(mtl V1)があり、その後に新機能のtype familiesを用いたmtl-tfが開発されたものの mtlと重複した部分が多く互換性もなかった。 そこで拡張なしの素のHaskell98で動くtransformersが開発され、 その上にmonads-fdとmonads-tfを別々に構築することで互換性の問題は解決された。 しかしその頃にはすでにmtlが広く使われていたため、transformersとmonads-fdからmtlを再構築(mtl V2)することになった、 という経緯のようです。

実際的な違いは、transformers はより古い Haskell で動く、mtl はより洗練された API を持っている、ということになりそうです。
Extensible Effectが保持するモナド数によらずに定数時間で処理できるのはなぜなんですか?(この記事です https://konn-san.com/prog/haskell/extensible-effects.html
ありがとうございます。「Haskell入門 関数型プログラミング言語の基礎と実践」読書会に伝えてこちらの slack のことも宣伝しておきます。
2つのライブラリーがあって、 MonadError SomeException m => m a な文脈の中で MonadThrow m => m a な関数を使いたくなったんですが、混ぜるハックありますかね?
foo :: MonadError SomeException m => m a
foo = do
  -- ここで使いたい
  -- 型はライブラリー A で決まってある

bar :: MonadThrow m => m a
-- これを使いたい
-- 型はライブラリー B で決まってある
まず、MonadErrorとはmtlのでしょうか?
それから、これの意図はMonadThrowのthrowMをMonadErrorのthrowErrorにするようにしたいということでしょうか?
MonadErrorとはmtlのでしょうか?
そうです
それから MonadThrow は exceptions のです
これの意図はMonadThrowのthrowMをMonadErrorのthrowErrorにするようにしたいということでしょうか?
そうですね。例えば一旦捕えて投げ直すとか。
MonadErrorはパラメータeが必要な気がするんですが、そこにはSomeExceptionを当てはめる想定ですか?
おっとそうでした。元の投稿を直しました。
either throwM pure (bar :: Either SomeException a)

or

newtype MonadThrowWrapper m a = W (m a) deriving (Functor, Applicative, Monad)
instance MonadError SomeException m => MonadThrow (MonadThrowWrapper m) where
throwM = W . throwError . toException
monadThrowToError :: forall me a. MonadError SomeException me => (forall mt. MonadThrow mt => mt a) -> me a
monadThrowToError x = coerce (x @(MonadThrowWrapper me))

monadThrowToError bar
とかですかね?
下の方を参考にうまくいきましたー! :muscle:
なんかスマフォから打ってめっちゃ間違ってたのと書きかけだったので,いちよ修正しときました
論文をちゃんと読んでなくて、実装だけで理解してるので、もしかしたら不正確かもしれませんが…
たとえば、以下のようにMaybeモナドがたくさん重なったものを考えます。

type M5 = MaybeT (MaybeT (MaybeT (MaybeT Maybe)))


これのreturnとbind(>>=)を書き下してやると、重ねたモナドの数だけ型構築や型分解のコストが増えている事が分かります。

returnM5 :: a -> M5 a
returnM5 x= MaybeT $ MaybeT $ MaybeT $ MaybeT $ Just $ Just $ Just $ Just $ Just x

bindM5 :: M5 a -> (a -> M5 b) -> M5 b
bindM5 x = 
  case x of
    Nothing -> MaybeT $ MaybeT $ MaybeT $ MaybeT $ Nothing
    Just x ->
      case x of
        Nothing -> MaybeT $ MaybeT $ MaybeT $ MaybeT $ Just $ Nothing
        Just x -> ...


一方で、EEではOpen Unionという仕組みを使って、以下のようなデータ型をコンパイル時に生成します。

data M5' a = Just' a | Nothing1 | Nothing2 | Nothing3 | Nothing4 | Nothing5


これによって、いくら重ねるモナドが増えても型構築や型分解のコストが増えない、という訳です。
モナド→モナド変換子、ですね
階層になっていないから深く潜るためのコストがいらないってことですか。open-unionはただのunionとなにか違うんですか?
普通のunionというのは、Haskellの普通の和型、data T = A|B|Cのように、宣言の時点で要素を足し算して作る奴の事で、それに対してEE系パッケージに入っているopen-union(単にUnionとかの名前になっている事が多い)は「全体の型を明示せずに構築したりパターンマッチしたりできる」という特徴があります
使わないところはプレースホルダーでもおいて使えるんですね。詳しい説明ありがとうございます。
集合論・群論の本でわかりやすい本を教えてください。大学数学超初心者です。
math という部屋がありますので、そちらで聞くといいと思います。
個人的には、初歩的な分野で書籍数も比較的多いので、書店でパラパラめくって読めそうなものを選んだりamazonのレビュー高い本であればどれでも勉強できるのかなと思いました。
stack hoogle コマンドを普通に実行すると、現在開発している(stack.yamlを置いている)プロジェクトのインデックスを生成したいのか、開発中のプロジェクトのビルドを始めます。
これを、依存しているパッケージのドキュメントに対するインデックスの生成に限定することはできるでしょうか?
開発中のプロジェクトは、ビルドが通らない状態になっていることが多いので、開発中のプロジェクトが原因でインデックスを生成できないのはつらいです。
stack hoogle -- generate base ?
stack hoogle -- generate でいけました!
( :thinking_face: さっき手元の環境で openBinaryFile: invalid argument (Invalid argument) と出たのは何だったんだろう。。。)
いずれにしてもありがとうございます!
例えば
haskell
module Sonoda.Parser
#if ON_GHCI
  ( ParseException (..)
  , parseExpr
  , parseType
  , exprParser
  , typeParser
  ) where
#else
  where
#endif

のようにして、CLIで`stack ghci --on-ghci`みたいな感じ(感じ)でghciを起動したときにだけ
全てエクスポートしてくれるような方法を探しているのですが、何かないですか?:writing_hand:
:load コマンドでそのmoduleを読んだだけではダメなんですかね…

そりゃ敢えてやるとしたら、cabalファイルにflagを書いて、CPPの変数を定義すればできそうな気がしますが…
ついでに,other-modulesでInternalモジュールにしてそこでは全てexportし,exposed-modulesでreexportするのはダメなんですか?
:load コマンドでそのmoduleを読んだだけではダメなんですかね…

おっ、なるほど、:loadってexportされてない関数も読めるんですか!
ついでに,other-modulesでInternalモジュールにしてそこでは全てexportし,exposed-modulesでreexportするのはダメなんですか?
うーん、考えてみます。

お二人ともありがとうございます!
こんにちは。 HaskellでMessagePackのライブラリはどれを使えばよいかご存知の方、教えていただけますか?

data-msgpackというライブラリが該当するかと思い調べているのですが、 timestampの読み込みで、このコードだと、 2バイト目以降を読んでいるように思うのですが、 msgpackの仕様をみると、2バイト目は“Type”なので、読むなら3バイト目以降じゃないといけない気がしてます。ちゃんとテストすればいいのですが、そもそもこのライブラリでよいのかどうか自信がなく、深入りするまえにおたずねしています。

https://github.com/TokTok/hs-msgpack/blob/ecfa24d5e237639597797b8e826b37e92efe4fe3/src/Data/MessagePack/Get.hs#L146

https://github.com/msgpack/msgpack/blob/master/spec.md#ext-format-family
ほかに同じように使っている人がいればいいんですが、ちょっといなければ深入りするしかなさそうですね。。。 :disappointed:
windowsでHDBC-mysql使っている方いますか?
こちらの記事やhdbc-mysqlのissueを見ると使うの結構大変そうだなと思ったのですが、どちらもある程度古い記述のため、もしかしたら周辺環境とかで状況変わってないかなと。
http://tsubaki.hatenablog.com/entry/20121020/1350734844
半年ほど前だったか試してみましたが libmysqlclient をリンカー(?)にうまく探してもらえなくて1日格闘して、諦めて VM にしました
@kakkun61 ありがとうございます!
なるほど、、かなり苦戦する点ありそうですね。
格闘する前に感触知れて助かりました。
(まさにwinで動くように頑張るか、vmにするか検討してる状況でした)
@tsubaki has left the channel
ソースを非公開のままで Haskell 製のライブラリを提供する方法を探してます。
ソース非公開のパッケージを作る方法(= pre built なバイナリ + ヘッダのようなもの)ってありますでしょうか?
DLLや.soファイルとして公開するなら GHCの -shared オプションが使えそうですけども、そういう話ではないんですよね。。。
その場合、その .so で提供される関数を Haskell からコールするには、なにかしら FFI をかまさないといけないですよね。
そっすね。
参考にするとしたら http://www.kotha.net/ghcguide_ja/7.0.4/separate-compilation.html らへんの話ですかね。
ソースファイルをコンパイルするとき、GHCはふつう二つのファイルを出力する。オブジェクトファイルとインタフェースファイルである。

オブジェクトファイルは通常.oで終わり、そのモジュールのコンパイル済みコードを含む。

インタフェースファイルはふつう.hiで終わり、そのモジュールに依存するモジュールをコンパイルするときに必要な情報を含む。エクスポートされた関数の型や、データ型の定義といったものがこれに含まれる。バイナリ形式なので、読もうとしないように。代わりに—-show-ifaceオプションを使うことができる。