Home
Insert
Update snippet 'Emulating higher level typing using inline functions and member constraints'
Title
Passcode
Description
This pattern shows that by using a few static member constraints, one can create an assortment of data processing functions that emulate higher level typing than is possible in F#.
Source code
let inline iter (f : 'a -> unit) (x : 's) = (^s : (member Iter : ('a -> unit) -> unit) x,f) let inline iterBack (f : 'a -> unit) (x : 's) = (^s : (member IterBack : ('a -> unit) -> unit) x,f) let inline empty () = (^s : (static member Empty : 's) ()) let inline (+>) item col = (^s : (member AddFirst : 'a -> 's) col,item) let inline (<+) col item = (^s : (member AddLast : 'a -> 's) col,item) let inline (<+>) col1 col2 = (^s : (static member Concat : 's -> 's -> 's) col1,col2) let inline (++>) items col = (^s : (member AddManyFirst : #seq<_> -> 's) col,items) let inline (<++) col items = (^s : (member AddManyLast : #seq<_> -> 's) col,items) //++ Advanced Operators //The following operators deal with adding or removing items from a data structure. ///Returns the first elements of the data structure let inline takef n col = (^s : (member TakeFirst : int -> ^s) col,n) ///Returns the last elements of the data structure let inline takel n col = (^s : (member TakeLast : int -> ^s) col,n) ///Splits the data structure at the specified index. let inline split n col = (^s : (member Split : int -> ^s * ^s) col,n) ///Gets the first element of the data structure let inline first col = (^s : (member First : 'a) col) ///Gets the last element of the data structure let inline last col = (^s : (member Last : 'a) col) ///Gets the element with the specified index from the data structure let inline get i col = (^s : (member Item : int -> ^a) col,i) ///Sets the element with the specified index from the data structure let inline set i v col = (^s : (member Set : ^k * 'a -> 's) col,i,v) ///Removes the first element from the data structure. let inline dropf col = (^s : (member DropFirst : ^s) col) ///Removes the last element from the data structure. let inline dropl col = (^s : (member DropLast : ^s) col) let inline fromSeq (sq : #seq<_>) = (^s : (static member FromSeq : seq<'a> -> 's) sq) ///Reverses the data structure. let inline reverse col = (^s : (member Reverse : ^s) col) ///Gets the length of the data structure. let inline length col = (^s : (member Length : int) col) //++ Derived Operators // These operators use the above operators to apply functions on data structure, filter, etc. let inline splice index inner outer = let part1,part2 = outer |> split index let part1 = part1 <+> inner let closed = part1 <+> part2 closed let inline droplMany n target = let len = target |> length let first = target |> takef (len - n) first let inline dropfMany n target = let len = target |> length let last = target |> takel (len - n) last let inline insertManyAt index (sq : seq<'a>) (target : ^s) = let ins = (sq |> fromSeq) target |> splice index ins let inline removeAt index target = let part1,part2 = target |> split index let part1 = part1 |> dropl part1 <+> part2 let inline removeManyAt index count target= let part1,part2 = target |> split index let part1 = part1 |> droplMany count part1 <+> part2 let inline insertAt index item target = let part1,part2 = target |> split index let part1 = part1 <+ item let closed = part1 <+> part2 closed ///Applies the specified transformation on the data structure. let inline map (f : 'a -> 'b) col = let refRoot = ref (empty() : 'b) let mapIter x = let x = x |> f refRoot := (!refRoot <+ x) col |> iter mapIter !refRoot ///Filters the data structure using the specified predicate. let inline filter (f : 'a -> bool) (col : 's) : 's = let refRoot = ref (empty() : ^s) let filterIter (x : 'a) = if f x then refRoot := !refRoot <+ x col |> iter filterIter !refRoot ///Applies a a function on the data structure, keeping all elements which return Some, and dropping all those that return None. let inline choose (f : _ -> _ option) col = let refRoot = ref (empty() : 'b) let chooseIter x = match f x with | None -> () | Some y -> refRoot := !refRoot + y col |> iter chooseIter !refRoot ///Constructs a linked list from the elements of this data structure let inline toList col = let refList = ref [] let listIter x = refList := x :: !refList col |> iter listIter !refList ///Folds over the data structure using the specified function. let inline fold (foldr : _-> _ -> _) (start : _) col = let refState = ref start let foldIter x = refState := foldr (refState.Value) x col |> iter foldIter !refState ///Folds over the data structure backwards, using the specified function. let inline foldBack (foldr :_ -> _ -> _) (start :_) col = let refState = ref start let foldbIter x = refState := foldr (refState.Value) x col |> iterBack foldbIter !refState ///Returns true if the specified predicate is true for all items in the data structure. let inline forall (pred : _ -> bool) col = col |> fold (fun cur item -> cur && pred(item)) true ///Returns true if the specified predicate is true for any item in the data structure. let inline forany (pred : _ -> bool) col = col |> fold (fun cur item -> cur || pred(item)) false ///Counts the number of items for which the specified predicate is true. let inline count (pred : _ -> bool) col = col |> fold (fun cur item -> if pred(item) then cur + 1 else cur) 0 let inline toArray col = let l = col |> length let arr = Array.zeroCreate l for i,item in Seq.zip {0 .. l} col do arr.[i] <- item arr
Tags
typeclass
inline
member constraints
data structures
polymorphism
typeclass
inline
member constraints
data structures
polymorphism
Author
Link
Reference NuGet packages
If your snippet has external dependencies, enter the names of NuGet packages to reference, separated by a comma (
#r
directives are not required).
Update