有人可以提供以下计划的机器实施吗?

时间:2013-06-26 17:20:41

标签: haskell transducer-machines

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

机器一和二坐在两个叉子的叉子上。

机器1将整数列表作为参数,然后将其推送到下游。 机器2将字符列表作为参数,并将其推送到下游。

机器3保持内部状态,从mempty开始,然后mappends在某些条件下从Wye基础上从任一台机器接收的元素(因此不是两者)。机器3然后获得当前状态并推动它下降。

Machine 4将收到的元素打印到控制台。

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

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

1 个答案:

答案 0 :(得分: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中使用过monoid,我使用的是普通数字,但这个想法是一样的。我还使用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比使用明确的monadic循环要快一些,但我认为在这个小例子中差异可以忽略不计。

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