Используя 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

Тогда вам просто нужно предоставить составное состояние большего размера и подходящие линзы, чтобы управлять всем этим.

Другие вопросы по тегам