4

「適切に」netwire 5に動的なワイヤセットを実装しようとしています。私はワイヤーのワイヤーの質問への回答を読みましたが、例のコードが動作に変換されて、の1回の実行Event空でないことを示す方法に依存する方法が特に好きではありません.stepWire

Eventしたがって、 s を介して動的セットにワイヤを追加および削除したいと考えていUnsafe.Eventます。Wire簡単にするために削除部分を削除し、 sを追加できるようにしましょう。

dynWireSet1 :: (Monad m, Monoid s)
            => Wire s e m (a, Event (Wire s e m a b)) [b]

各イベントは、内部に隠されているワイヤーの (最初は空の) リスト (または他のセット) に新しいワイヤーを追加し、それらはすべて実行され、すべて type の入力を取得し、aそれらの出力をリストに収集します。

実行部分は比較的簡単で、グーグルで検索できる例があります。

dynWireSet1 = runWires1 []
runWires1 :: (Monad m, Monoid s)
          => [Wire s e m a b]
          -> Wire s e m (a, Event (Wire s e m a b)) [b]
runWires1 wires = mkGen $ \session (input, event) -> do
  stepped <- mapM (\w -> stepWire w session (Right input)) wires
  let (outputs, newwires) = unzip stepped
  return (sequence outputs, runWires1 newwires)

上記の例はイベントを無視します。event関数 from以外では、遷移関数内でイベントを使用することは不可能であると思われUnsafe.Eventます。あれは正しいですか?避けたいUnsafe.Event

一歩下がって、推奨されているイベントの使用方法を確認すると、非常に有望な関数が表示されます。

krSwitch :: Monad m
         => Wire s e m a b
         -> Wire s e m (a, Event (Wire s e m a b -> Wire s e m a b)) b

さて、単純化された runWires から始めるとどうなるでしょうか:

runWires2 :: (Monad m, Monoid s)
          => [Wire s e m a b]
          -> Wire s e m a [b]
runWires2 wires = mkGen $ \session input -> do
  stepped <- mapM (\w -> stepWire w session (Right input)) wires
  let (outputs, newwires) = unzip stepped
  return (sequence outputs, runWires2 newwires)

dynWireSet を krSwitch にします。

dynWireSet2 :: (Monad m, Monoid s)
            => Wire s e m (a, Event (Wire s e m a b)) [b]
dynWireSet2 = krSwitch (runWires2 []) . second (mkSF_ (fmap addWire))
addWire :: Wire s e m a b -> Wire s e m a [b] -> Wire s e m a [b]
addWire = undefined

私はほとんどそこにいます!ここで、新しいワイヤーをに挿入するfmapだけでよければ、準備は完了です。しかし、これは一般的なケースでは不可能です。実際、私が正しく理解すれば、出力のすぐ上にあります。使い物にならない。(:)runWires2newwiresfmapWGenfmaps

そして今、ここに私の考えがあります。の新しいバリアントを紹介しましょう。内部状態を異なるデータ型で保持するため、data Wire暫定的に呼び出します。WCarry g stその遷移関数はタイプになります

((a, c) -> m (b, c))

そして、初期状態が与えられると、コンストラクターは次のような Wire を生成します。

mkCarry :: Monad m => ((a, c) -> m (b, c)) -> c -> Wire s e m a b
mkCarry transfun state = mkGenN $ \input -> do
  (output, newstate) <- transfun (input, state)
  return (Right output, mkCarry transfun newstate)

結果のワイヤーにWCarryタイプの代わりにタイプを導入するだけです。の観点WGenから再定式化するのは簡単です。runWiresmkCarry

次に、fmap インスタンスは次のようになります。

fmap f (WCarry g st) = WCarry g (fmap f st)

これにより、「hidden inside」状態オブジェクトが変更さkrSwitchれ、この種の s で function を有意義に使用Wireして、以前の値を失うことなく内部状態を微調整できるようになります。

これは理にかなっていますか?私がやろうとしていることがより簡単な方法で可能であれば、アドバイスをお願いします! 私が話していることが理にかなっている場合、どうすればそれを行うことができますか? WCarry を使用して定義をローカルに拡張し、data Wire対応する定義を持つ興味深い Class インスタンスを拡張して追加することは可能ですか? 他にアドバイスはありますか?

ありがとう。

4

1 に答える 1

2

私は Netwire を使用していましたが、まったく同じ問題に遭遇したので、これに回答すると役立つと思います。(安全な) イベントを使用することが正しい方法であることに同意します。ただし、 を追加するのは好きWCarryではありません。あまり直感的ではないようです。

あなたは実際に答えに非常に近かった。作成の鍵addWireは、古いワイヤを「変更」したくないことに依存しています。あなたが望むのは、指定されたサブワイヤの出力を追加して新しいワイヤを作成することです。これはあなたが探していたものかもしれません:

addWire w ws = fmap (uncurry (:)) (w &&& ws)

このワイヤは両方のワイヤに給電し、出力を結合します。それが役に立てば幸い!

于 2015-12-13T17:15:04.693 に答える