Lists and Seq's each have an outstanding "feature" which helps you decide which to use.
For a list, the "feature" is that it has the structure hd::tl, which makes left-to-right processing and pattern matching easy, and computationally efficient.
For a seq, the "feature" is that it lazy evaluated, ie. the "head" element is only computed when it is used. Thus a seq can be used for input, in a way that lists can't.
Example 1 - Use a seq for large, or infinite, sequences
Aim: Print the first leaf of a very large list of lists (or seq of seqs)
open List
let test_big_list =
let chunk = [1..10000000]
let mem_hog = [ for i in 1..10000000 -> chunk]
printf "First leaf = %i\n" (hd (hd mem_hog))
test_big_list
open Seq
let test_big_seq =
let chunk = seq {1..10000000}
let mem_hog = seq { for i in 1..10000000 -> chunk }
printf "First leaf = "%i\n" (hd (hd mem_hog))
test_big_list
If you put both of these in the interpreter, you'll find:
- The List version takes several seconds to compute, or causes an out-of-memory error, because the whole structure is built in memory before the "printf" is invoked.
- The seq version is evaluated instantly, because it only computes the first element.
Example 2 - Use a list for manipulating structured data
Aim: Given a list, or seq, "double" it, by making each element appear twice
let rec double_up = function
| [] -> []
| hd::tl -> hd::hd::(double_up tl)
With a list, this is too easy! :)
Seq is much less obvious, and involves application of two functions..
let rec double_up_s s = Seq.map_concat (fun a -> seq [a;a]) s
(it took me quite a while to work that out, after looking for a more direct solution)
--------------------------------
I agree that it is hard finding this stuff in the books, but it is there.
See Syme p 463 for file i/o with a Seq
Harrop (F# for Scientists) p. 130 has a beautiful example of file i/o with Seq.
let lines_of_file filename =
seq { use stream = File.OpenRead filename
use reader = new StreamReader(stream)
while not reader.EndOfStream do
yield reader.ReadLine() }
Then he reads the first three lines with...
lines_of_file "my_text.txt" |> Seq.take 3;;
Now that's when a compution expression is more than sytactic sugar!
For me, the difference between Lists and Seqs is that List is a data structure and Seq is a computation.
I agree the outstanding feature of Lists is pattern matching or structural decomposition. This allows you to write recursive functions over the structure of Lists. You can't do this (efficiently) with Seqs because they have no structure, they're a computation (you can't pattern match a function).
I don't see lazy evaluation as the outstanding feature of Seqs though. You can have a LazyList, it is a data structure like a List, enjoys structural decomposition like a List, but it is lazyily evaluated. Seqs on the other hand are a computation, so if that computation is a generator function that evaluates the next element then yes that looks lazy, but if that computation just looks up the element from a List already in memory then it is not really any more lazy than the List itself.
What I do see as the outstanding feature of Seqs is stream fusion.
1 2 3 4
let list0 = [1..1000000] let list1 = List.map (fun x -> 2 * x) list0 let list2 = List.filter (fun x -> x % 2 = 0) list1 let list3 = List.map (fun x -> x / 2) list2
In this code I allocate a list of a million elements (list0), then I map over it and allocate another list of one million elements (list1), then I filter it and there's another million, and then another. So at the end of the day I have 4 million list nodes in memory. If I wrote the same code with Seqs then
1 2 3 4
let list0 = [1..1000000] let seq1 = Seq.map (fun x -> 2 * x) list0 let seq2 = Seq.filter (fun x -> x % 2 = 0) seq1 let seq3 = Seq.map (fun x -> x / 2) seq2
I still allocate a million nodes for my initial list. But each time I perform an operation on it, I am not copying the entire list because the Seq.* functions build a computation rather than transform a data structure. So at the end of this code the memory contains just 1 million list nodes and 3 Seq computation objects.
So how fast are conversions to/from Seq, like List.of_seq or Seq.of_array?
And the only "pairwise" function in the library is Seq.pairwise but it's easy to follow the same "template" and write "pairwise" that operates on lists, or that operates on a list and returns pairs in ResizeArrays, etc. So unless conversions to/from Seq are very cheap, I wonder why there is not List.pairwise etc.
Conversions to seq are no-ops (upcasts - Lists and Arrays and whatnot implement IEnumerable<T>).
Conversions from seq to concrete types are O(N) in time and space. But so is any 'creation of a new collection', so in a sense this is 'as cheap as possible' (from a big-oh perspective anyway).
Seq.pairwise works great for concrete collections.
I like the description of the 'outstanding features'.
Seq is much less obvious, and involves application of two functions..
let rec double_up_s s = Seq.map_concat (fun a -> seq [a;a]) s
(it took me quite a while to work that out, after looking for a more direct solution)
Here's an easy solution:
1 2 3 4 5 6
let DoubleUp s = seq { for x in s do yield x yield x }
I'll try to help out a bit.
The Seq type is IEnumerable, correct (it's just a type alias, AFAIK). F# List, BCL's List<T>(ResizeArray), Array -- they all implement the IEnumerable interface, and hence are all Seqs.
The important thing to understand about IEnumerable/seq is that it is simply a forward-only, read-only enumeration type. While it can be backed by arrays and lists, it could also be backed by code that generates values as needed. For example, reading a file or reading a database recordset could be viewed as IEnumerables.
Sequence computations (seq { for ... }) have counterparts: lists are "[ for ... ]" and array is "[| for ... |]".
Seq has more functions cause a seq function can work across all seq types, not just list, array, etc. The difference is that a generic sequence-based function won't always be as efficient. For example, doing length on an array is O(1). Doing length on a sequence is O(n). But, the F# team is also still cleaning up those modules so expect them to change some still.
In your example of doing List.of_seq on a ResizeArray, that's what's expected, because a ResizeArray IS a seq: it implements IEnumerable.
Does that help some?
yes that helps, thanks.
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
I'm a bit mystified about the Seq datatype, which I understand is for the IEnumerable datatype. It doesn't seem "parallel" to the F# List, Array and ResizeArray datatypes. Yet the textbooks about F# don't really discuss Seq. It seems like an ugly stepchild.
1. When I pass in a C# list to an F# function, on the F# side it appears as Seq .
2. There's the seq { for ....... } statement which produces a Seq . There's no similar statement that produces a List or anything else.
3. Microsoft.FSharp.Collections contains more functions for Seq than for List, ResizeArray, Array, etc. For example Seq.pairwise . Odd treatment if it's an ugly stepchild.
4. Sometimes it acts like a ResizeArray: below the input is a ResizeArray but is converted to a List with List.of_seq (not List.of_ResizeArray)
let Max ( input :
ResizeArray<int>) =
let output = List.of_seq(input)
List.max(output)
5. Sometimes it acts only sort-of like a ResizeArray. input_array is of type Seq in the statement below, which compiles, but VS tells me that the accum_array on the RHS is of type Seq and on the LHS it is of type ResizeArray.
let accum_array = Seq.map2 (fun x y -> x + y) accum_array input_array
6. It can be converted formally to a ResizeArray using the Microsoft.FSharp.Collections functions, only by making it a List first, even though a List seems less similar:
let sample_list = Resize.of_list ( List.of_seq sample_seq )
Is there some clear way to understand how Seq fits into the F# language?