Is there any other idiomatic ways to pass state information?

f#

Solution

A purely functional solution would be to use the `fold` function. The `fold` function is used to process a sequence (or a list) and accumulate some state. In your example, the state is the `lastTakenId` and also the list of elements that you want to return, so you can use state of type `Timestamp * (Timestamp list)`:

let hourlyTicks = 
  readTicks @"EURUSD-history.zip" "EURUSD-2012-04.csv" 
  |> Seq.fold (fun (lastTakenId, res) tickAt ->
      // Similar to the body of your stateful function - 'lastTakenId' is the last
      // state and 'tickAt' is the current value. The 'res' list stores 
      // all returned elements
      let tickId = tickAt / HOUR 
      if tickId <> lastTakenId then  
        // We return new state for 'lastTakenId' and append current element to result
        (tickId, tickAt::res)
      else 
        // Here, we skip element, so we return the original state and original list
        (lastTakenId, res) ) (-1L, []) // Initial state: -1 and empty list of results

  // Take the second part of the state (the result list) and
  // reverse it, because it was accumulated in the opposite order
  |> snd |> List.rev

Aside, I'm not entirely sure about your other pure solution - I don't think it does exactly the same thing as the first one (but I don't have the data to test), because you're only comparing two adjacent elements (so, perhaps, in the first one, you may skip multiple items?)

Problem

I have a need to process a sequence of historical tick data of millisecond timeframe. The ability is required to filter in opening ticks of certain timespans (hourly, minute, etc.). The sequence may have gaps greater, than the span, so the first tick after such gap must be picked as opening one, otherwise the opening tick is one that is closest to pass of calendar beginning of correspondent timespan. The first thing that comes to my mind is the following stateful filtering function `opensTimespan:Timespan->(Timestamp->bool)` that captures timespanId of each gap-opening or interval-opening tick into a closure for passing between invocations: ``` let opensTimespan (interval: Timespan)= let lastTakenId = ref -1L // Timestamps are positive fun (tickAt: Timestamp) -> let tickId = tickAt / interval in if tickId <> !lastTakenId then lastTakenId := tickId; true else false ``` and can be applied like this: ``` let hourlyTicks = readTicks @"EURUSD-history.zip" "EURUSD-2012-04.csv" |> Seq.filter (opensTimespan HOUR) |> Seq.toList ``` This works fine, but `opensTimespan` having the side effect is definitely not idiomatic. One alternative may be using the fact that the decision upon a tick is opening one or not requires just the pair of timestamps of the self and the previous one to come up with the following stateless filtering function `opensTimespanF:Timespan->Timestamp*Timestamp->bool`: ``` let opensTimespanF interval (ticksPair: Timestamp*Timestamp) = fst ticksPair/ interval <> snd ticksPair/ interval ``` that can be applied as: ``` let hourlyTicks= seq { yield 0L; yield! readTicks @"EURUSD-history.zip" "EURUSD-2012-04.csv" } |> Seq.pairwise |> Seq.filter (opensTimespanF HOUR) |> Seq.map snd |> Seq.toList ``` This approach being pure functional produces equivalent results with only a slight (~11%) performance penalty. What other way(s) of approaching this task in pure functional manner I may be missing? Thank you.

Original source