3

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

一号和二号机器位于 Wye 的两个叉子上。

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

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

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

到目前为止,我有这个:

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

4

1 回答 1

5

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

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,因为我的示例需要确定性输入 - 它选择是否从Lor读取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)改用。完整代码在这里

于 2013-06-26T20:14:39.590 回答