Используя Data.Machine, как вы можете составить два ProcessT вместе, который изменяет два разных состояния?
Допустим, у меня есть процесс, который изменяет основное состояние, которое является Int
:
p1 :: ProcessT (State Int) Int Int
p1 = repeatedly $ do
a <- await
lift . modify $ (+a)
yield a
И другой, который изменяет основное состояние, которое является [Int]
:
p2 :: ProcessT (State [Int]) Int Bool
p2 = repeatedly $ do
a <- await
lift . modify $ (++[a])
as <- get
if length as > 3 then yield True else yield False
Я хочу составить их так:
p3 = source [1...6] ~> p1 ~ p2
И запустить их как:
flip runState 0 . flip runState [] . runT $ p3
Но я получаю эту ошибку:
Couldn't match expected type `Int' with actual type `[Int]'
Expected type: ProcessT (State Int) Int c0
Actual type: ProcessT (State [Int]) Int Bool
In the second argument of `(~>)', namely `p2'
In the expression: source [1 .. 6] ~> p1 ~> p2
Предполагая, что p1 и p2 должны иметь один и тот же тип основного состояния. Фактически, небольшой эксперимент показывает, что p1 и p2 фактически изменяют одно и то же основное состояние. Как я могу обойти это?
1 ответ
Решение
Вы можете сделать большее состояние и изменить каждое вычисление, чтобы перевести линзу в большее составное состояние для системы.
p1 :: (MonadState s m, Num a) => Lens' s a -> ProcessT m a a
p1 l = repeatedly $ do
a <- await
l += a
yield a
Тогда вам просто нужно предоставить составное состояние большего размера и подходящие линзы, чтобы управлять всем этим.