I'm still working on feeling for the F # thing - trying to figure out how to “think” in F #, and not just translate it from other languages that I know.
I recently thought of cases where you do not have a 1: 1 card between before and after. Cases when List.map crashes.
One example of this is moving averages, where you usually get len-n + 1 results for a list of len lengths when averaged over n elements.
For the guru, is this a good way to do this (using the queue pinched from Jomo Fisher )?
type Fifo<'a> =
new()={xs=[];rxs=[]}
new(xs,rxs)={xs=xs;rxs=rxs}
val xs: 'a list;
val rxs: 'a list;
static member Empty() = new Fifo<'a>()
member q.IsEmpty = (q.xs = []) && (q.rxs = [])
member q.Enqueue(x) = Fifo(q.xs,x::q.rxs)
member q.Length() = (List.length q.xs) + (List.length q.rxs)
member q.Take() =
if q.IsEmpty then failwith "fifo.Take: empty queue"
else match q.xs with
| [] -> (Fifo(List.rev q.rxs,[])).Take()
| y::ys -> (Fifo(ys, q.rxs)),y
module List =
let splitat n lst =
let rec loop acc n lst =
if List.length acc = n then
(List.rev acc, lst)
else
loop (List.hd lst :: acc) n (List.tl lst)
loop [] n lst
let MovingAverage (len:int) (lst:float list) =
let qMean (q:Fifo<float>) = ((List.sum q.xs) + (List.sum q.rxs))/(float (q.Length()))
let (init, rest) = List.splitat len lst
let q = new Fifo<float>([], init)
let rec loop (acc:float list) ls (q:Fifo<float>) =
match ls with
| [] -> List.rev acc
| h::t ->
let nq = q.Enqueue(h)
let (nq, _) = nq.Take()
loop ((qMean nq)::acc) t nq
loop [qMean q] rest q
MovingAverage 3 [1.;1.;1.;1.;1.;2.;2.;2.;2.;2.]
(Maybe the best way would be to implement MovingAverageQueue, inheriting from Fifo?)
source
share