Это разумный способ сбора входов сети?
Я хотел бы использовать провод типа Wire s e m a b
обрабатывать несколько входов. Предполагаемая семантика будет
- Если список ввода
[]
ничего не делать и вернуть пустой список - Если список ввода
a:as
пошаговый провод со входомa
, рекурсивно пошагово получаемый провод с вводомas
, а затем собрать результаты в список
Разве это разумно? Является ли моя реализация разумной? Запреты здесь полностью игнорируются, что кажется странным. Как правильно создать провода, которые обрабатывают "несколько событий одновременно" в сети?
many :: (Monoid s, Monad m) => Wire s e m a b -> Wire s e m [a] [b]
many w = mkGen (\s as -> do
(bs, w') <- go s w as
return (Right bs, many w'))
where go _ w' [] = return ([], w')
go s w' (a:as) = do
(e, w'') <- stepWire w' s (Right a)
(bs, w''') <- go s w'' as
let b = case e of Right r -> [r]
Left _ -> []
return (b ++ bs, w''')
1 ответ
На ваш вопрос довольно сложно ответить, поскольку абстракции действительно полезны только для приложений, которые их используют. Игнорирование торможения само по себе не является проблемой, но вы теряете много функциональности из-за таких вещей, как Alternative
класс типов.
Предположим, у вас есть провод, который преобразует нажатия клавиш в действия и блокирует, когда ни одна клавиша не нажата:
inputWire :: Wire s e m Key Action
Вы можете создать провод, который возвращается к действию по умолчанию, если первый провод запрещает:
defaultAction :: Wire s e m a Action
defaultAction = ... whatever ...
actionWire :: Wire s e m Key Action
actionWire = inputWire <|> defaultAction
Если вы хотите создать что-то, что обрабатывает несколько входов, в идеале вы хотели бы сделать что-то вроде:
actionWire :: Wire s e m [Key] [Action]
actionWire = (many inputWire) <|> (defaultAction >>> (arr (: [])))
... но это не будет работать с вашей реализацией. Вы можете добавить охрану для проверки непустых списков из many
но вы делаете что-то гораздо более многословное, чем нужно.
Однако, возражение, которое @Cubic упомянул об отсутствии семантики непрерывного времени, является проблемой. Предположим, у вас есть провод, который переключается в течение определенного времени:
foo :: Wire s e m a b
bar :: Wire s e m a b
-- This wire pulses the action of a key to be move or moveFast
pulseFooBar :: Wire s e m a b
pulseFooBar = (foo >>> (for 3)) -->
(bar >>> (for 3)) -->
pulseFooBar
В этом примере pulseFooBar
будет обрабатывать ввод как foo
в течение трех секунд, а затем как bar
в течение трех секунд, а затем чередовать обратно. В данном контексте, many pulseFooBar
не имеет никакого смысла. Так как вы шагаете несколько раз в любой данный временной шаг, pulseFooBar
больше не переключается каждые три секунды, и становится зависимым от входа и времени между временными шагами.