Upload
jack-fox
View
399
Download
1
Tags:
Embed Size (px)
DESCRIPTION
Condensed version of my Lambda Jam talk presented to the N.Y. City F# User Group
Citation preview
Functional Linear Data Structures Form a Semantically Coherent Set
Jack Foxjackfoxy.com craftyThoughts
@foxyjackfox
Bibliographyjackfoxy.com/Lambda_Jam_fsharp_bibliography
Sample Codegithub.com/jackfoxy/FunctionalLinearDataStructures
• Orderby construction / sorted / random
• Evaluationeager / lazy
• Peekfirst / last / indexed
• Constructionfirst / last / insert
• Remove (Deconstruct)first / last / indexed
choose 1
choose 1
choose 1 – 2, or #3
choose 0 – 2, or #3
choose 0 – 2, or #3
(insert only for sorted & random)
Seq lets you transform structures
let thisIsTrue = seq {1..10} |> Array.ofSeq |> Deque.ofSeq |> DList.ofSeq |> FlatList.ofSeq |> Heap.ofSeq false |> LazyList.ofSeq |> Queue.ofSeq |> RandomAccessList.ofSeq |> Vector.ofSeq |> List.ofSeq = [1..10]
…and apply any of 68 Seq Module functions
seq {1.0..10.0} |> Heap.ofSeq false |> Seq.average
seq {1..10} |> Deque.ofSeq |> Seq.fold (fun state t -> (2 * t)::state) []
seq {1..10} |> RandomAccessList.ofSeq |> Seq.mapi (fun i t -> i * t)
seq {1..10} |> Vector.ofSeq |> Seq.reduce (fun acc t -> acc * t )
Unfold Infinite Sequences
unfold starts here
Markov chaintype Weather = Sunny | Cloudy | Rainy
let nextDayWeather today probability = match (today, probability) with | Sunny, p when p < 0.05 -> Rainy | Sunny, p when p < 0.40 -> Cloudy | Sunny, _ -> Sunny | Cloudy, p when p < 0.30 -> Rainy | Cloudy, p when p < 0.50 -> Sunny | Cloudy, _ -> Cloudy | Rainy, p when p < 0.15 -> Sunny | Rainy, p when p < 0.75 -> Cloudy | Rainy, _ -> Rainy
let NextState (today, (random:Random), i) = let nextDay = nextDayWeather today (random.NextDouble()) printfn "day %i is forecast %A" i nextDay Some (nextDay, (nextDay, random, (i + 1L)))
let forecastDays = Seq.unfold NextState (Sunny, (new Random()), 0L)
printfn "%A" (Seq.take 5 forecastDays |> Seq.toList)> day 0 is forecast Sunny day 1 is forecast Sunny day 2 is forecast Cloudy day 3 is forecast Rainy day 4 is forecast Cloudy [Sunny; Sunny; Cloudy; Rainy; Cloudy]
printfn "%A" (Seq.skip 5 forecastDays |> Seq.take 5 |> Seq.toList) > day 0 is forecast Sunny
… day 9 is forecast Sunny [Cloudy; Rainy; Sunny; Cloudy; Sunny]
printfn "don't try this at home! %i" (Seq.length forecastDays)
printfn "don't try this at home either! %A" (forecastDays |> List.ofSeq)
So far:Linear Structures as an abstraction
Seq as the unifying abstraction
Sequences are sequential (duh!)
Next:More choices
printfn "%A" (Seq.take 5 forecastDays |> Seq.toList)printfn "%A" (Seq.take 7 forecastDays |> Seq.toList)
> day 0 is forecast Sunny day 1 is forecast Cloudy day 2 is forecast Sunny day 3 is forecast Sunny day 4 is forecast Cloudy [Sunny; Cloudy; Sunny; Sunny; Cloudy] day 0 is forecast Sunny day 1 is forecast Sunny day 2 is forecast Sunny day 3 is forecast Sunny day 4 is forecast Sunny day 5 is forecast Sunny day 6 is forecast Cloudy [Sunny; Sunny; Sunny; Sunny; Sunny; Sunny; Cloudy]
Inconsistent!
LazyList: seq-like & List-likelet lazyWeatherList = LazyList.unfold NextState (Sunny, (new Random()), 0L)printfn "%A" (LazyList.take 3 lazyWeatherList)
> day 0 is forecast Sunny day 1 is forecast Sunny day 2 is forecast Cloudy [Sunny; Sunny; Cloudy]
printfn "%A" (LazyList.take 4 lazyWeatherList)
> day 3 is forecast Cloudy [Sunny; Sunny; Cloudy ; Cloudy]
Skip always evaluates
LazyList.ofSeq (seq {for i = 1 to 10 do yield (nextItem i)})|> LazyList.skip 2|> LazyList.take 2|> List.ofSeq
> item 1 item 2 item 3 item 4
O(1) Appendlet observedWeatherList =
LazyList.ofList [Sunny; Sunny; Cloudy; Cloudy; Rainy;]
let combinedWeatherList = LazyList.append observedWeatherList
lazyWeatherList
printfn "%A" (LazyList.skip 4 combinedWeatherList |> LazyList.take 3)> day 0 is forecast Rainy
day 1 is forecast Cloudy seq [Rainy; Rainy; Cloudy]
Observed Predicted
List - like
[ ]
Construct Deconstruct
Tail
Head
1
empty
::
…and the only data element accessible!
Vector
54321
Construct Deconstruct
Initial
Last
[ ]
empty
;;
Multiway Forest
Multiway Treetype 'a MultiwayTree = {Root: 'a; Children: 'a MultiwayForest}
with…
and 'a MultiwayForest = 'a MultiwayTree Vector
let inline create root children = {Root = root; Children = children}
let inline singleton x = create x Vector.empty
Queue ::
1 ;;
Deconstruct
Construct
DList ::
1 ;;
Construct Deconstruct
Construct
…
Tail
Head
Tail
Head
Breadth 1st Traversal
let inline breadth1stForest forest = let rec loop acc dl =match dl with| DList.Nil -> acc| DList.Cons(head, tail) ->
loop(Queue.conj head.Root acc)(DList.append tail (DList.ofSeq
head.Children))
loop Queue.empty (DList.ofSeq forest)
What areWe Missing?
We’ve seen
The right structure for the right job
RandomAccessList
54321
Construct Deconstruct
Tail
Head
[ ]
empty
::
Deque (double-ended queue)
5::
1
Head Tail
;;
Init LastConstruct Deconstruct
Construct Deconstruct
Heap (ordered)
::
1
Head Tail
Deconstruct
Construct
Graphics: http://www.turbosquid.com/3d-models/heap-gravel-max/668104
Deletions?
What Else?Random Stack
Purely Functional Circular Buffer
Questions?