Создать сигнал из списка
Можно ли создать Signal
из List
? По сути, я хочу что-то с подписью List a -> Signal a
, Я знаю что Signal
представляет изменяющееся во времени значение, и поэтому что-то подобное на самом деле не имеет никакого смысла (т.е. я не могу придумать причину использовать его в производственном коде).
Я мог видеть приложения этого для тестирования все же. Например, представьте некоторую функцию, которая зависела от прошлых значений Signal
(с помощью foldp
например), и вы хотели сделать утверждения о состоянии системы, учитывая, что сигнал получил значения x, y и z.
Обратите внимание, что не должно быть ничего особенного в Signal
обозначает, что он только когда-либо получит фиксированное количество значений. Я думаю об этом больше как: в производстве у вас есть Signal
щелчков мыши, и вы хотите проверить, что из заданной начальной позиции после заданного набора щелчков система должна быть в каком-то другом известном состоянии. Я знаю, что вы могли бы смоделировать это, вызывая функцию фиксированное число раз и передавая результаты обратно с новыми значениями, мне просто интересно, возможно ли это.
2 ответа
Я думаю, это возможно. Вы используете сигнал на основе времени и сопоставляете значения из списка:
import Time
import Graphics.Element exposing (show)
list = [1..10]
signalFromList : List a -> Signal a
signalFromList list =
let
(Just h) =
List.head list
time =
Time.every Time.second
maybeFlatMap =
flip Maybe.andThen
lists =
Signal.foldp (always <| maybeFlatMap List.tail) (Just list) time
in
Signal.filterMap (maybeFlatMap List.head) h lists
main = Signal.map show <| signalFromList list
Тем не мение!
Не должно быть трудно проводить тестирование без сигналов. Если у тебя есть foldp
где-то в тесте вы можете использовать List.foldl
по списку [x,y,z]
вместо. Это должно дать вам возможность смотреть на состояние вашей программы после ввода x
, y
, z
,
Я не думаю, что есть какой-то способ сделать это синхронно в чистом вязе (ответ Апанацки хорошо иллюстрирует, как настроить последовательность событий во времени и почему это плохая идея). Если мы посмотрим, как определяется большинство сигналов, то увидим, что они все в какой-то момент направляются в нативный пакет.
Тогда возникает вопрос: можем ли мы сделать это изначально?
f : List a -> Signal a
Я часто думаю о (Сигнале а) как о "а, который меняется со временем". Здесь мы предоставляем список as и хотим, чтобы функция меняла его с течением времени.
Прежде чем мы продолжим, я рекомендую быстро взглянуть на Native / Signal.js: https://github.com/elm-lang/core/blob/master/src/Native/Signal.js
Допустим, мы приехали на родину с нашим списком как. Мы хотим что-то вроде Signal.constant, но с некоторым дополнительным поведением, которое "отправляет" каждый a впоследствии. Когда мы можем сделать отправку, хотя? Я предполагаю, что мы не можем сделать это во время функции построения сигнала, так как мы все еще строим график сигнала. Это оставляет нам пару других вариантов:
- что-то отвратительное с setTimeout, планируя отправку каждого "а" в соответствующий момент в будущем
- проектирование ловушки во время выполнения elm, чтобы мы могли выполнить произвольный обратный вызов в точке, когда граф сигналов полностью построен
По крайней мере, для меня первое звучит чревато ошибками, и я надеюсь, что второе не существует (и никогда не существует)!
Для тестирования вы бы предложили мне использовать сгиб List для имитации поведения foldp.