Рефакторинг труб
Я собираю модель кодера, используя библиотеку каналов (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