【问题标题】:Could someone provide a machines implementation of the following plan?有人可以提供以下计划的机器实施吗?
【发布时间】:2013-06-26 17:20:40
【问题描述】:

我正在玩 Edward Kmett 的机器模块,我在这里和那里有点困惑。我认为提出问题的最佳方式是提供一个玩具用例。如下所述。

一号机和二号机位于 Wye 的两个尖头上。

机器将一个整数列表作为参数,并将其推送到下游。 机器二将一个字符列表作为参数,并将其推送到下游。

机器 3 保持内部状态,从 mempty 开始,然后是 mappends 在某些条件下它从 Wye 基地的任一机器接收到的元素(所以不是两者)。然后机器 3 获取当前状态并将其推送到下游。

机器四将它接收到的元素打印到控制台。

到目前为止,我得到了这个:

y1 :: PlanT k [Int] m ()
y1 = yield

y2 :: PlanT k [Char] m ()
y2 = yield

但我不确定如何组合 y1 和 y2;或滚动隐藏状态的任意进程,而不是使用 Process.hs 导出的库存组合器之一。

根据建议,机器包的链接: http://hackage.haskell.org/package/machines

还有一个 pdf 对其功能进行了非常高级的描述:https://dl.dropboxusercontent.com/u/4588997/Machines.pdf

【问题讨论】:

  • 为什么这个问题被否决了?
  • @jerry @closevoters machines新的。 Edward Kmett 值得一看,值得你努力去了解他所做的新事物。如果这对您来说很明显,请回答。如果你不清楚,可能是因为machines 的我们现在很多人都不清楚。如果你理解pipesconduit,那么说这不是很好的措辞是可以的,但是如果你根本不理解它,那可能是因为它是最前沿的,你应该先去理解管道之前你来决定这是否可以更好地表达。
  • @AndrewC 自the version I was commenting on 以来,该问题已被多次编辑。该版本实际上没有包含问题(或关于 chibro2 试图做什么的陈述)。
  • @RyanWH 据我了解,Wye 是“机器”,可以以不确定的方式从两个输入流中读取,因此机器三可以从字符列表或整数列表中读取,并构建一个新的列表。但是新列表只包含整数或字符,而不是两者。问题的关键在于如何组合不同的机器来制造更大的机器,这里发生的事情是偶然的。很抱歉,如果这也表达得不好。
  • @AndrewC 你说得对,我不明白machineplan 的特殊含义,但我仍然坚持我(最初)没有看到问题的评论.大多数用户不认为“为我编写代码”是 Stack Overflow 上的一个有效问题(不过,就个人而言,如果我觉得这个话题足够有趣,有时我还是会回答)。值得称赞的是 chibro2,他或她已经改进了这个问题,以至于我觉得它适合该网站(尽管我对 Haskell 或 machines 概念的熟练程度还不够,无法尝试一下)。跨度>

标签: haskell transducer-machines


【解决方案1】:

我也是机器初学者,这是我的结果:

import Control.Monad
import Data.Char (intToDigit)
import Data.Machine
import Data.Machine.Plan
import Data.Machine.Source

-- | Produces integers from a list.
m1 :: [Int] -> Source Int
m1 = source

-- | Produces characters from a list.
m2 :: [Char] -> Source Char
m2 = source

-- | Reads a number from its left input. Then reads this many
-- characters from its right input. Outputs the resulting string,
-- together with the number of strings produced so far.
m3 :: Tee Int Char (Int, String)
m3 = construct (loop 0)
  where
    -- `loop` keeps internal state - the count of strings
    -- produced so far.
    loop count = do
        -- Read a number from L.
        n <- awaits L
        -- Read this many characters from L.
        s <- replicateM n (awaits R)
        let count' = count + 1
        -- Output the result.
        yield (count', s)
        loop count'

main = print . run $ tee (m1 [2,3,4,5])
                         (m2 "Lorem ipsum dolor sit amet") m3

我没有在m3 中使用过幺半群,而是使用纯数字,但想法是一样的。我还使用了Tee 而不是Wye,因为我的示例需要确定性输入——它选择是从L 还是R 读取。但将Wye 用于类似目的也是一样的。

更新:当然可以使用State 而不是Identity 来跟踪计数。例如:

m3State :: TeeT (State Int) Int Char (Int, String)
m3State = repeatedly $ do
        n <- awaits L
        s <- replicateM n (awaits R)
        lift (modify (+ 1)) -- increment the counter
        count <- lift get   -- get the counter to output it
        yield (count, s)

main = print . flip evalState 0 . runT $ input m3State

我怀疑在计划中使用repeatedly 比使用显式单子循环稍快,但我认为在这个小例子中差异可以忽略不计。

或者如果我们只想计算字符串的数量并仅在最后输出,我们可以使用Writer (Sum Int) 代替。完整代码here.

【讨论】:

  • 这太棒了!几乎正是我想要的。有什么办法 Tee 可以包装一个 State monad?这样计数可以通过调用modify (+1) 来增加,而不是显式调用loop count',我们可以写循环计数=永远$ do {...}?
  • @chibro2 是的,我更新了示例。我注意到 machines 有一个特殊的组合器 repeatedly,我怀疑它会稍微快一些。
猜你喜欢
  • 1970-01-01
  • 2010-12-21
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
  • 2021-02-26
  • 1970-01-01
相关资源
最近更新 更多