gpt4 book ai didi

haskell 网络: wires of wires done properly

转载 作者:行者123 更新时间:2023-12-02 17:57:10 26 4
gpt4 key购买 nike

我正在尝试“正确”地在 netwire 5 中实现一组动态电线。我已阅读wires of wires的答案问题,而且我不太喜欢示例中的代码如何依赖于转换为行为的 Event恰好一次执行上显示非空>stepWire.

因此,我想通过 Event 在动态集中添加和删除连线,并且希望不会利用 Unsafe.Event 或同等黑客行为。为了简单起见,让我们删除删除部分,只添加Wire:

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

每个事件都会将一条新连线添加到隐藏在其中的连线(最初为空)列表(或其他组)中,并且它们都运行,都获取 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)

上面的示例忽略事件。我怀疑这是不可能的在转换函数中使用事件,而不是通过来自 Unsafe.Eventevent 函数。那是对的吗?我想要避免 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

我快到了!现在,如果我只能在 runWires2fmap 一个 (:) 并将新线插入 newwires,我就万事俱备了!但这在一般情况下是不可能的。事实上,如果我理解正确的话,WGen 上的 fmap 只是输出上的 fmaps 。没用。

现在,这是我的想法。让我们介绍一下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 类型。根据 mkCarry 重新表述 runWires 很容易。

然后,fmap 实例将如下所示:

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

它将改变“隐藏在内部”的状态对象,我们将能够在这种Wire上有意义地使用krSwitch函数来调整它们的内部状态而不丢失之前的值。

这有道理吗?如果我想做的事情可以以更简单的方式实现,请提出建议!如果我所说的有道理,我该怎么做呢?是否可以使用 WCarry 本地扩展 data Wire 定义,并扩展添加具有相应定义的有趣的类实例?还有其他建议吗?

谢谢。

最佳答案

我正在使用 Netwire,遇到了完全相同的问题,所以我认为回答这个问题会很有用。我同意使用(安全)事件是正确的方法。不过我不喜欢添加 WCarry,它看起来不太直观。

您实际上非常接近答案。 addWire 的关键在于您不想“修改”旧电线。您想要的是创建一条新线路,并添加给定子线路的输出,因此这可能就是您正在寻找的内容:

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

这根电线为两条电线供电,然后连接输出。希望对您有帮助!

关于 haskell 网络: wires of wires done properly,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33129623/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com