Skip to content

Commit ed03800

Browse files
authored
Proper SeqT implementation (#485)
1 parent 879d652 commit ed03800

File tree

7 files changed

+1495
-48
lines changed

7 files changed

+1495
-48
lines changed

docsrc/content/type-seqt.fsx

+73-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,83 @@
11
(*** hide ***)
22
// This block of code is omitted in the generated HTML documentation. Use
33
// it to define helpers that you do not want to show in the documentation.
4-
(**
5-
TO-DO Add some docs here !
6-
=========================
4+
5+
// For some reason AsyncDownloadString is not found during doc build. The following is a dumb implementation just to make the compiler happy.
6+
// TODO find out why.
7+
type System.Net.WebClient with member wc.AsyncDownloadString (uri: System.Uri) = async { return wc.DownloadString uri }
8+
9+
(*
10+
SeqT<Monad<bool>, 'T>
11+
=====================
12+
13+
This is the the Monad Transformer for `seq<'T>` so it adds sequencing to existing monads by composing then with `seq<'T>`.
14+
15+
Any monad can be composed, but a very typical usage is when combined with `Async` or `Task`, which gives rise to what's called async sequences.
16+
17+
Therefore the [AsyncSeq](https://github.com/fsprojects/FSharp.Control.AsyncSeq) library can be considered a specialization of this monad in Async.
18+
19+
The original post from AsyncSeq can be found [here](http://tomasp.net/blog/async-sequences.aspx) and we can run those examples with `SeqT` by adapting the code.
20+
21+
In order to do so we need to be aware of the design differences of both implementations.
22+
23+
| AsyncSeq | SeqT | Notes |
24+
|--|--|:--:|
25+
|`AsyncSeq<'T>` |`SeqT<Async<bool>, 'T>` | |
26+
|`asyncSeq { .. }` |`monad.plus { .. }` | At some point it needs to be inferred as `SeqT<Async<bool>, 'T>`, or it can be specified with type parameters: `monad<SeqT<Async<bool>, 'T>>.plus` |
27+
|`let! x = y` |`let! x = SeqT.lift y` | No auto lifting. Lifting should be explicit. |
28+
|`do! x` |`do! x` | '' |
29+
|`for x in s` |`let! x = s` | When `s: AsyncSeq<'T>` otherwise `for` is still ok with regular sequences. |
30+
|`AsyncSeq.[function]` |`SeqT.[function]` | See differences in functions below. |
31+
|`AsyncSeq.[function]Async` |`SeqT.[function]M` | '' |
32+
|`AsyncSeq.skip` |`SeqT.drop` | `.skip` is available but consistently with F# collections, it throws when the sequence doesn't have enough elements. |
33+
|`AsyncSeq.take` |`SeqT.truncate` | `.take` is available but consistently with F# collections, it throws when the sequence doesn't have enough elements. |
34+
|`AsyncSeq.toBlockingSequence` |`SeqT.run >> Async.RunSynchronously` | Not really the same but semantically equivalent. |
35+
|`AsyncSeq.toListAsync` |`SeqT.runAsList` | |
36+
|`AsyncSeq.toArrayAsync` |`SeqT.runAsArray` | |
37+
|`AsyncSeq.zipWith` |`SeqT.map2` | Aligned with F# collections. |
38+
|`AsyncSeq.zipWithAsync` |`SeqT.map2M` | '' |
39+
|`AsyncSeq.ofObservable` |`Observable.toAsyncSeq` |`.toAsyncTask` is also available. |
40+
|`AsyncSeq.toObservable` |`Observable.ofAsyncSeq` |`.ofAsyncTask` is also available. |
41+
42+
743
844
Examples
945
--------
1046
*)
1147

12-
1348
#r @"../../src/FSharpPlus/bin/Release/net45/FSharpPlus.dll"
1449

15-
open FSharpPlus
50+
open System
51+
open System.Net
52+
open FSharpPlus
53+
open FSharpPlus.Data
54+
55+
let urls =
56+
[ "http://bing.com"; "http://yahoo.com";
57+
"http://google.com"; "http://msn.com"; ]
58+
59+
// Asynchronous sequence that returns URLs and lengths
60+
// of the downloaded HTML. Web pages from a given list
61+
// are downloaded asynchronously in sequence.
62+
let pages: SeqT<_, _> = monad.plus {
63+
use wc = new WebClient ()
64+
for url in urls do
65+
try
66+
let! html = wc.AsyncDownloadString (Uri url) |> SeqT.lift
67+
yield url, html.Length
68+
with _ ->
69+
yield url, -1 }
70+
71+
72+
// Print URL of pages that are smaller than 100k
73+
let printPages =
74+
pages
75+
|> SeqT.filter (fun (_, len) -> len < 100000)
76+
|> SeqT.map fst
77+
|> SeqT.iter (printfn "%s")
78+
79+
printPages |> Async.Start
80+
81+
(*
82+
To make it work with tasks simply add `|> Async.StartAsTask` between `wc.AsyncDownloadString (Uri url)` and `|> SeqT.lift` then run eveything but the `printPages |> Async.Start`.
83+
**)

0 commit comments

Comments
 (0)