問題タブ [monad-transformers]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
3 に答える
734 参照

haskell - リーダーモナドをスナップで使用する(または、モナド変換子をスナップで使用する)

誰かがリーダーモナド内でスナップモナドを使用する方法を示すことができますか?モナド変換子は私を混乱させます。(または、モナド変換子に関するチュートリアルの提案や、光を見て最終的にそれらをグロッキングする方法の提案を喜んで受け入れます。)

編集:おっと; 特定のことについて助けを求めるのではなく、私が実際にやろうとしていることを特定するのを忘れました。戦術ではなく戦略。特に、ルートを指定するときにそのデータベース接続/プールを明示的に渡す必要なしに、すべてのハンドラー間でデータベース接続/プールを共有したいと思います。リーダーモナドがそれを達成する方法のようです。

0 投票する
2 に答える
585 参照

haskell - Data.Binary.Putモナドをラップするとメモリリークが発生するのはなぜですか?(パート2)

前の質問と同様に、Data.Binary.Putモナドを別のモナドにラップして、後で「何バイトを書き込むか」や「ファイル内の現在の位置は何か」などの質問をすることができるようにしようとしています。 。

以前は、些細な(IdentityT?)ラッパーを使用しているときにメモリリークが発生する理由を理解することで、問題を解決できると思いました。しかし、皆さんが些細なラッパーの問題を解決するのを手伝ってくれたとしても、StateTやWriterTのような便利なものでラップすると、メモリを大量に消費します(通常はクラッシュします)。

たとえば、これは私がそれをラップしようとしている1つの方法であり、大きな入力のためにメモリをリークします。

これは、問題を示すより完全なコードサンプルです。

私が知りたいのはこれです:

  1. メモリリークの原因となるプログラム内で何が起こっていますか?
  2. それを修正するにはどうすればよいですか?

2番目の質問では、データがディスク上でどのように見えるかをより詳細に説明する必要があると思います。これは基本的に、ツリーの各ノードがその子(およびいくつかの追加データ)へのオフセットテーブルとして表されるツリー構造です。したがって、オフセットテーブルへのn番目の子のオフセットを計算するには、0からn-1までの子のサイズに現在のオフセットを加えたものを知る必要があります(簡単にするために、各ノードに固定数の子があるとします)。

見てくれてありがとう。

更新:nominoloのおかげで、Data.Binary.Putをラップし、現在のオフセットを追跡し、メモリをほとんど使用しないモナドを作成できるようになりました。これは、継続を使用する別の状態のスレッドメカニズムを優先して、StateTトランスフォーマーの使用をやめることによって行われます。

このような:

ただし、MyPutがディスクに書き込むバイト数の追跡にはまだ問題があります。特に、次のような署名付きの関数が必要です。

たp>

私のアプローチは、MyPutモナドをWriterTトランスフォーマー(このようなもの)内にラップすることでした。しかし、それは再びあまりにも多くのメモリを消費し始めました。sclvがnominolosの回答の下のコメントで言及しているように、WriterTは継続の効果をどういうわけかキャンセルします。彼はまた、私がすでに持っているMyPutモナドから直接サイズを取得できるはずだと述べていますが、そうしようとするすべての試みは、コンパイルできないコードまたは無限ループで終わりました:-|。

誰かがさらに助けてくれませんか?

0 投票する
5 に答える
2865 参照

haskell - 同じモナド変換子の異なる順序の違いは何ですか?

プログラムで特定のタイプのプロシージャを表現するためのAPIを定義しようとしています。

IDからレコードへのマッピングで構成される状態があります。

3つの基本的な操作があります。

これらの操作にはいくつかの目標があります。

  • プロシージャは、(生の呼び出しとは異なりMap.lookup)どのレコードが使用可能かについて仮定を立てることができ、それらの仮定のいずれかが間違っている場合、プロシージャは全体として失敗を返します。
  • <|>さまざまな仮定を行うプロシージャにフォールバックするために、(クラスAlternativeから)を使用して一連のプロシージャをチェーン化できます。(STMと同様orElse

これらの目標を考えると、モナドStateMaybeモナドの組み合わせが必要だと思います。

Maybeとの2つの順序がどのようにState異なるかを理解できません。2つの順序の動作の違いを誰かが説明できますか?

また、私の当初の考え方に問題がある場合(おそらく私は過剰に設計されています)、遠慮なく指摘してください。

結論: 3つの回答はすべて役に立ちましたが、どの順序が必要かを判断するのに役立つ一般的なアイデアが1つありました。runMaybeT/の戻りタイプをrunStateT見ると、どの組み合わせが私が探していた動作をしているのかが簡単にわかりました。(私の場合、リターンタイプが必要ですMaybe (ProcedureState, a))。

0 投票する
4 に答える
2204 参照

haskell - Haskellでツリーデータ構造をバイナリファイルに保存するにはどうすればよいですか?

Haskell を使用して、単純な (しかし非常に大きな) ツリー構造をバイナリ ファイルに保存しようとしています。構造は次のようになります。

そして、ディスク上でデータをどのように表示する必要があるかを次に示します。

  1. 各ノードは、その子への 4 つの 32 ビット オフセットで始まり、子に続きます。
  2. リーフについてはあまり気にしません。たとえば、n 個の連続した 32 ビットの数字だとしましょう。
  3. 実用的な目的で、いくつかのノード ラベルやその他の追加データが必要になりますが、今のところ、どちらもあまり気にしません。

Haskeller がバイナリ ファイルを作成する際に最初に選択するのは、Data.Binary.Put ライブラリであるように思えます。しかし、それで私は箇条​​書き#1に問題があります。特に、ノードをファイルに書き込もうとしているときに、子のオフセットを書き留めるには、現在のオフセットと各子のサイズを知る必要があります。

これは Data.Binary.Put が提供するものではないので、Monad トランスフォーマーの完璧なアプリケーションに違いないと思いました。しかし、クールで機能的に聞こえますが、これまでのところ、このアプローチは成功していません。

ここここで問題を解決するのに役立つと思われる他の 2 つの質問をしました。私は、私がさらに進歩するのに役立つ非常に素晴らしい回答を受け取るたびに、残念ながら私はまだ問題を全体的に解決することができていないと言わなければなりません.

ここに私がこれまでに得たものがありますが、まだメモリリークが多すぎて実用的ではありません。

このような機能的なアプローチを使用するソリューションがあれば幸いですが、他のソリューションにも感謝します。

0 投票する
2 に答える
5517 参照

haskell - Haskellの後藤:継続モナドの使用によるこの一見非常識な効果を誰かが説明できますか?

このスレッド(Control.Monad.Cont fun、2005)から、Tomasz Zielonkaが関数を導入しました(ThomasJägerによって明確で素晴らしい方法でコメントされています)。Tomaszは、callCC本体の引数(関数)を受け取り、次の2つの定義を使用して後で使用できるように返します。

それらはHaskellwikiでも言及されています。それらを使用すると、haskellのgotoセマンティクスに似たものになります。これは本当にクールに見えます。

これにより、0〜10の数値が出力されます。

ここに興味深い点があります。これをライターモナドと一緒に使って、ある問題を解決しました。私のコードは次のようになります。

このコードをコンパイルして実行すると、出力は次のようになります。

この例の深遠な暗闇のどこかで、0から3までの数字が飲み込まれています。

現在、「Real World Haskell」では、オサリバン、ゲルゼン、スチュワートの各州が

「モナド変換子の積み重ねは、関数の作成に似ています。関数を適用する順序を変更して、異なる結果が得られても、驚くことはありません。したがって、モナド変換子も同様です。」(Real World Haskell、2008、P.442)

上記のトランスを交換するというアイデアを思いつきました。

ただし、Control.Monad.ContにMonadWriterのインスタンス定義がないため、これはコンパイルされません(これが、最近この質問をした理由です)。

リッスンとパスを未定義のままにしてインスタンスを追加します。

それらの行を追加し、コンパイルして実行します。すべての数字が印刷されます。

前の例で何が起こったのですか?

0 投票する
1 に答える
515 参照

haskell - Data.Binary.Put モナドをトランスフォーマに変更するとメモリ リークが発生するのはなぜですか?

Data.Binary.PutM モナドをモナド変換子に変更しようとしています。だから私はそれの定義を変更することから始めました

それからもちろんreturn>>=関数の実装を変更しました:

から:

に:

PutM モナドが単なる Writer モナドであるかのように。残念ながら、これは(再び)スペースリークを引き起こしました。ghc がどこかで評価を延期していることは明らかですが、いくつかのチュートリアルで提案されているように、どこにでも配置しようとしまし$!$が、それは役に立ちませんでした。また、次のような場合、メモリ プロファイラーがどのように役立つかわかりません。

メモリ プロファイル.

完全を期すために、これは元の Data.Binary.Put モナドを使用したときに得られるメモリ プロファイルです。

元のメモリ プロファイル

興味がある場合は、テストに使用しているコードと、コンパイル、実行、およびメモリ プロファイルの作成に使用している行を次に示します

メモリ リークに関する私の一連の質問で誰かを悩ませていないことを願っています。インターネット上には、このトピックに関する優れたリソースがあまりないことがわかりました。

ご覧いただきありがとうございます。

0 投票する
2 に答える
337 参照

monads - なぜモナドの単位自然変換を定義するのか - これはエンドファンクターであるモナドの定義によって暗示されているのではないのですか?

  1. モナドは、カテゴリ C のエンドファンクタとして定義されます。たとえば、C には int 型と bool 型、およびその他の構築型がオブジェクトとして含まれているとします。ここで、このカテゴリに対して定義された list モナドについて考えてみましょう。

それは非常に定義されたリストであり、エンドファンクターであり、int型をList [int]にマップし(これは関数として解釈できますか?)、boolをList [bool]にマップし、(これも関数ですか?)モーフィズムintをマップします- > bool to List[int] -> List[bool]

ですから、これまでのところ、それは理にかなっています。しかし、私を深い混乱に陥れているのは、それに伴う必要のある自然な変換の追加定義です。Unit... int を List[int] に変換します (List ファンクターの定義はすでにこれを暗示していませんか? これは私が持っている大きな混乱の 1 つです

b. List ファンクターは、int から List[bool] ではなく、int から List[int] へのマッピングとして常に理解する必要がありますか?

c. int から List[int] へのユニットの自然な変換は、List をファンクターとして定義することによって暗示される int から List[int] へのマップとは異なりますか? これは私の以前の質問の再表明にすぎないと思います。

0 投票する
2 に答える
755 参照

haskell - モナドトランスフォーマーに内部モナド用の「replicateM」関数はありますか?

次のようなものがあるとします。

私の頭の中にあるのは、 に格納されるパラメータを持つ時間プロセスのシミュレーションですEnvironment。動的状態は に格納されMyState、シミュレーションの各時間ステップで収集したい情報は に格納されReportます。

ここで、このシミュレーションの多くのステップを実行して、各時間ステップのレポートを含むリストを取得したくありません。

私は通常、 なしでこれをReaderT行い、次のようにパラメーターを渡していました。

それから私はただやります:

liftとの型で混乱していますreplicateMState MyStateトランスフォーマー内でモナドを複製する組み合わせはありますか?

将来的には交換ReaderT Environment (State MyState) ReportするReaderT Environment (StateT MyState (Rand StdGen)) Reportので、このモンスタータイプになる前に物事を正しく取得することをお勧めします:(.

編集:副次的な質問として-使用するよりも良い戦略はありReaderT Environment (State MyState) Reportますか?

0 投票する
4 に答える
396 参照

haskell - インターフェイス抽象化の設計

現在、趣味のプロジェクトとして小さなゲーム プログラム (Skat) を作成しようとしています。Skat は、2 人のプレイヤーが 1 人のプレイヤーと対戦するトリックテイキング ゲームです。プレーヤーにはさまざまな種類 (ローカル プレーヤー、ネットワーク プレーヤー、コンピューターなど) があるため、プレーヤーへのインターフェイスを抽象化したいと考えました。

私の基本的なアイデアは、 typeclass を使用することですPlayer。これは、プレイヤーがしなければならないことや知っておくべきことすべてを定義します (カードをプレイする、誰がトリックに勝ったかについて通知を受けるなど)。次に、ゲーム全体playSkat :: (Player a, Player b, Player c) => a -> b -> c -> IO ()a、 、bおよびcさまざまな種類のプレーヤーである関数によって行われます。プレーヤーは、実装で定義された方法で反応する場合があります。ローカル プレイヤーは自分の端末で何らかのメッセージを受信し、ネットワーク プレイヤーはネットワークを介して何らかの情報を送信し、コンピューター プレイヤーは新しい戦略を計算します。

プレイヤーは何らかの IO を実行したい場合があり、プライベートなものを追跡するためにある種の状態を確実に持ちたい場合があるため、ある種のモナドに存在する必要があります。Playerそこで、次のようにクラスを定義することを考えました。

このパターンはステート トランスフォーマーに非常に似ているように見えますが、どのように処理すればよいかわかりません。IO の上に追加のモナド変換子として書くとしたら、一日の終わりには 3 つの異なるモナドができました。この抽象化をうまく書くにはどうすればよいでしょうか。

明確にするために、通常の制御フローは次のようになります。
トリックをプレイするとき、最初のプレイヤーがカードをプレイし、次に 2 番目のプレイヤーがプレイし、最後に 3 番目のプレイヤーがカードをプレイします。これを行うには、ロジックplayCardでプレーヤーごとに関数 trice を実行する必要があります。その後、ロジックは、どのプレイヤーがトリックに勝つかを決定し、勝った情報をすべてのプレイヤーに送信します。

0 投票する
1 に答える
4015 参照

haskell - Monad トランスフォーマー ライブラリ - どれを使うべきか?

Hackage には多くの異なるモナド変換ライブラリがあります。いくつかは他のものよりも注目を集めているようです。いくつか例を挙げると、mtl (何らかの理由でトランスフォーマーに依存する現在のバージョン)、transformers、monadLib、monads-tf、mtlx、contstuff などがあります。

どちらを優先する必要がありますか?その理由は? それらのユニークな機能は何ですか? パフォーマンスはどうですか?