Рефакторинг труб

Я собираю модель кодера, используя библиотеку каналов (4.1.4).

У меня есть рабочая функция

encode :: (Monad m) => Int -> -                 -- number of codes per bit
                       Producer Word32 m r ->   -- code source
                       Producer Word32 m r ->   -- data source
                       Producer Word32 m r      -- resulting stream
encode n cp dp = P.zipWith xor cp (dp >-> (upsample n))

И я хотел бы изменить его как

encode :: (Monad m) => Int -> 
                       Producer Word32 m r ->
                       Pipe Word32 m r

Я думаю, что его использование более понятно; он кодирует данные, проходящие через канал. У меня нет первой идеи, как этого добиться.

РЕДАКТИРОВАТЬ

upsample :: Int -> Pipe Word32 Word32 m r

1 ответ

Решение

Я думаю, что вам нужно это:

encode n cp = upsample n >-> f cp where
  f c = do
           r <- lift $ next c
           case r of
             Left r -> return r -- use f cp here, if you really meant Viginere
             Right (x, c') -> do
                             y <- await
                             yield $ x `xor` y
                             f c'

Вот encode будет ждать значения от cp: если оно станет доступным, оно запомнит значение и получит одно значение из upsample трубы, yield закодированное значение и цикл до encode остаток от Producer осталось от cp после удаления x, Таким образом, он будет повторять cp и данные параллельно, так же, как zipWith,


Я не знаю что upsample это как, поэтому я определил как отрицательный канал:

upsample :: Monad m => Int -> Pipe Int Int m r
upsample n = do
               x<-await
               yield $ -x
               upsample n

encode n cp = (upsample n) >-> f cp where
  f cp = do
           r <- lift $ next cp
           case r of
             Left r -> return r
             Right (x,cp) -> do
                               y <- await
                               yield $ x*y -- I was lazy to import Bits
                               f cp

Prelude Pipes> runEffect $ mapM_ yield [0..] >->
                           encode 10 (mapM_ yield [1..10]) >->
                           sequence_ (repeat $ do {x <- await; lift $ print x})
0
-2  -- remember, [0..] is negated by upsample, then multiplied by [1..10]
-6
-12
-20
-30
-42
-56
-72
-90  -- only 10 items were available in `cp`, so only 10 items printed
Другие вопросы по тегам