Search code examples
elmelm-signal

Create a Signal from a List


Is it possible to create a Signal from a List? Essentially what I want is something with the signature List a -> Signal a. I know that a Signal represents a time-varying value and so something like this doesn't actually make any sense (i.e. I can't think of a reason to use it in production code).

I could see applications of it for testing though. For example, imagine some function which depended on the past values of a Signal (via foldp for instance) and you wanted to make assertions about the state of the system given the signal had received values x, y, and z.

Note that there wouldn't have to be anything special about the Signal denoting that it only would ever receive a fixed number of values. I'm thinking of it more like: in production you have a Signal of mouse clicks, and you want to test that from a given starting position, after a given set of clicks, the system should be in some other known state. I know you could simulate this by calling the function a fixed number of times and feeding the results back in with new values, I'm just wondering if it is possible.


Solution

  • I guess it's possible. You use a time-based signal, and map the values from the list over it:

    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
    

    However!

    It shouldn't be hard to do testing without signals. If you have a foldp somewhere, in a test you can use List.foldl over a list [x,y,z] instead. That should give you the ability to look at the state of your program after inputs x, y, z.