Создать сигнал из списка

Можно ли создать 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.

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