TP

Asynchronous C# and F# (I.): Simultaneous introduction

One of the exciting new technologies that was announced at PDC 2010 is the support for asynchronous programming in C#. So what exactly is asynchronous programming? Many applications today need to connect to some service or external data source including, for example, Web Services and REST APIs. These calls may take a long time to run, but we want to run them without blocking the application.

Currently, you can run the operation on a background thread or using a Task, but coordinating multiple such operations is difficult. What if you for example need to wait until any (or all) of downloads complete and run some more code then? This is not only difficult, but it also scales badly, because blocking .NET threads is a bad practice (Threads are expensive and when they're just waiting for other operation to complete, we're wasting valuable resources). This problem has been the main motivation for including asynchronous workflows in F# about 3 years ago. In F#, this also enabled various interesting programming styles - for example creating GUI using asynchronous workflows (also discussed in Chapter 16 of my book and in in my recent talk). The C# asynchronous programming support and the await keyword is largely inspired by F# asynchronous workflows (I was quite surprised that F# wasn't more visibly mentioned in the PDC talk).

In this article series, I'll demonstrate both F# and C# asynchronous programming model, I'll look at features that are missing in one or the other as well as a few subtle differences (that may be unexpected) and finally, I'll write about writing (asynchronous) F# libraries that are easy to use from C#. The plan for the series is following:

Let's start with a brief overview of asynchronous programming features in C# and F#...

Published: Friday, 29 October 2010, 4:34 AM
Tags: c#, asynchronous, f#
Read the complete article

F# Parallel Extras (III.): Financial dashboard with cancellation

In this article we'll look at several improvements that can be done to the Financial dashboard example (originally from the Parallel Programming with Microsoft .NET book). When I was translating samples in the book from C# to F#, the sample struck me, because it looks like a perfect fit for F# asynchronous workflows (instead of the Task<T> type used in the C# version). I already talked about an alternative implementation based on asynchronous workflows. However that version was still following some of the programming patterns, from the original C# version, which are not idiomatic in F#. In this article, I'll talk about a few other improvements that we can make to the sample...

In the original version of the sample (in both C# and F#), we explicitly checked whether a cancellation token has been cancelled in every single operation. This was needed in C#, because tasks do not support cancellation automatically. However, F# asynchronous workflows make cancellation easier. They automatically check if the computation should be cancelled at the beginning and the end of every asynchronous call. Our first change will be to use this feature. Also, the original version propagates a null value when the computation is cancelling. In F# we don't need that and we'll only change the type of the overall result to option<T>, so that we can notify the user interface (but we don't need to propagate cancellation explicitly). Finally, the original version contained sequential implementation, but didn't provide any way of actually running it, so we'll do a bit of refactoring to make that sample actually useable.

Published: Wednesday, 27 October 2010, 11:13 AM
Tags: functional, parallel, asynchronous, f#
Read the complete article

F# Parallel Extras (II.): Agent-based blocking queue

In the previous article, we briefly introduced the BlockingQueueAgent<T> type and we used it to implement the pipeline pattern (from Chapter 7 of Parallel Programming with Microsoft .NET) using asynchronous workflows. The type was used to represent intermediate buffers with a limited size. In this article we'll take a look at the implementation of the type. The type implements a very useful pattern in agent-based parallel programming, so you can use it in your work, but it could be also interesting as a demonstration of the F# Agent<T> type (an recommended alias for the MailboxProcessor<T> type).

The BlockingQueueAgent<T> type is similar to BlockingCollection<T> from .NET 4.0. It has methods for adding and removing elements that block when the operation cannot be done (e.g. adding when the queue is full or removing when the queue is empty). The most important difference is that it can be used asynchronously. This means that when we call its operations form F# asynchronous workflow (using let! and do!), the operation will block the calling workflow, but it will not block any physical thread. We start by looking at the overall structure of the agent and then look at the body of the agent which implements its behavior (using a state machine)...

Published: Wednesday, 27 October 2010, 11:12 AM
Tags: functional, parallel, asynchronous, f#
Read the complete article

F# Parallel Extras (I.): Image pipeline using agents

In a recent blog post series, I wrote about parallel programming samples that accompany the Parallel Programming with Microsoft .NET book by patterns & practices group at Microsoft. The F# translation of the samples that I wrote about mostly followed the style used in the book, so it used patterns that are typical for C#. However, some of the samples can be written in F# in a more interesting way...

In this article, we'll take a look at agent-based implementation of the Image pipeline example (from chapter 7). A pipeline is a useful pattern if you need to process large number of inputs in parallel and the processing consists of multiple phases or steps. In the original implementation, the pipeline was implemented using BlockingCollection<T> and Task<T> types from .NET 4.0.

In this article, I'll show a version that uses F# agents and asynchronous workflows. We'll use a BlockingQueueAgent<T> type, which is discussed in another article. It represents a queue with limited capacity that asynchronously blocks the process that is adding values if there is no space in the buffer and blocks the process that reads values when there are no values. This type can be elegantly used to implement the pipeline pattern. In this article, we'll demonstrate it by writing a four-phase pipeline that processes images. As you'll see, the agent-based version of the code is very much easier to write and has similar performance as the original version.

Published: Wednesday, 27 October 2010, 11:11 AM
Tags: functional, parallel, asynchronous, f#
Read the complete article

Reactive, parallel and concurrent programming in F# (PADL 2011)

Don Syme blogged about a paper on the F# Asynchrounous Programming Model that I helped to write. Without any doubt, the asynchronous programming features of F# are one of the reason for its success and also influence other teams in Microsoft. However, I'm very glad that there is now also an academic paper that makes this idea accessible to the academic community. I believe that the ideas could evolve in interesting ways when used in other programming languages and also, it is now easier to create research projects that build on top of the F# model.

Don already mentioned that we have another paper accepted at PADL. The paper describes work that started during my internship at Microsoft Research in 2009. It presents a simple language extension for computation expressions that makes them even more useful in some reactive, concurrent and parallel programming models. Note that this is only a research project and there are currently no plans to support the extension in the F# language (although, if there will, eventually, be an open-source F# release, then you'll hear about the extension again...)

Here is the abstract of the paper (accepted at PADL 2011) and a PDF download link:

Joinads: A retargetable control-flow construct for reactive, parallel and concurrent programming

Modern challenges led to a design of a wide range of programming models for reactive, parallel and concurrent programming, but these are often difficult to encode in general purpose languages. We present an abstract type of computations called joinads together with a syntactic language extension that aims to make it easier to use joinads in modern functional languages.

Our extension generalizes pattern matching to work on abstract computations. It keeps a familiar syntax and semantics of pattern matching making it easy to reason about code, even in a non-standard programming model. We demonstrate our extension using three important programming models – a reactive model based on events; a concurrent model based on join calculus and a parallel model using futures. All three models are implemented as libraries that benefit from our syntactic extension. This makes them easier to use and also opens space for exploring new useful programming models.

The paper can still be revised before the final publication, so any comments and suggestions for improvement are largely welcome. You can contact me either via comments (below) or using email at tomas@tomasp.net. I would be also quite interested to hear from anybody who would like to implement similar feature in other programming languages (for example Haskell or Scala).

Published: Monday, 25 October 2010, 12:00 AM
Tags: f#, research, links, joinads
Read the complete article

Looking under the cover (How does it work?)

Languages with type-inference make it possible to write shorter code, because a smart compiler infers the types automatically. Even though we don't write the types, they are still there and are used to check whether our code doesn't contain (certain type of) bugs. However, types are not only useful for safety, but also when understanding code. When you see a function together with its type (especially higher-order functions) you can understand code much more easily than when you just see its name. When writing F# code, you can see all the types thanks to great integration for Visual Studio. However, what if you post a code sample to a web site or a blog? Many F# code snippets (including some on this blog) are just difficult to read without types.

A few weeks ago, I was talking with James Margetson (from the F# team) about the possible uses of some functionality provided by the F# compiler and he suggested that we could use them to solve the problem I described in the introduction. Wouldn't it be nice if you could place a mouse cursor over an identifier in an F# blog post and see the same type information as the one that would appear in Visual Studio?

Here is an example of what I'm talking about:

1: /// Asynchronously download the content of a web page
2: let downloadUrl url = (...)
3: 
4: /// Download specified pages and add their lengths
5: let getTotalLength urls = async { 
6:   let! texts = 
7:     urls |> List.map downloadUrl
8:          |> Async.Parallel
9:   return texts |> Seq.sumBy String.length }F# Web Snippets

If you cannot wait and want to create F# source code snippets like this yourself, then go straight to F# Web Snippets (please use the web based version carefully - processing is pretty demanding!). If you first want to know how it works and how to use it, as well as where to get the source code, then continue reading...

namespace System
namespace System.IO
namespace System.Net
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Control
module WebExtensions

from Microsoft.FSharp.Control
val downloadUrl : string -> Async<string>

Full name: Untitled.downloadUrl

Asynchronously download the content of a web page
val url : string

  type: string
  implements: IComparable
  implements: ICloneable
  implements: IConvertible
  implements: IComparable<string>
  implements: seq<char>
  implements: Collections.IEnumerable
  implements: IEquatable<string>
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val req : WebRequest

  type: WebRequest
  implements: Runtime.Serialization.ISerializable
  inherits: MarshalByRefObject
type HttpWebRequest =
  class
    inherit System.Net.WebRequest
    member Abort : unit -> unit
    member Accept : string with get, set
    member AddRange : int -> unit
    member AddRange : int * int -> unit
    member AddRange : string * int -> unit
    member AddRange : string * int * int -> unit
    member Address : System.Uri
    member AllowAutoRedirect : bool with get, set
    member AllowWriteStreamBuffering : bool with get, set
    member AutomaticDecompression : System.Net.DecompressionMethods with get, set
    member BeginGetRequestStream : System.AsyncCallback * obj -> System.IAsyncResult
    member BeginGetResponse : System.AsyncCallback * obj -> System.IAsyncResult
    member ClientCertificates : System.Security.Cryptography.X509Certificates.X509CertificateCollection with get, set
    member Connection : string with get, set
    member ConnectionGroupName : string with get, set
    member ContentLength : int64 with get, set
    member ContentType : string with get, set
    member ContinueDelegate : System.Net.HttpContinueDelegate with get, set
    member CookieContainer : System.Net.CookieContainer with get, set
    member Credentials : System.Net.ICredentials with get, set
    member EndGetRequestStream : System.IAsyncResult -> System.IO.Stream
    member EndGetRequestStream : System.IAsyncResult * System.Net.TransportContext -> System.IO.Stream
    member EndGetResponse : System.IAsyncResult -> System.Net.WebResponse
    member Expect : string with get, set
    member GetRequestStream : unit -> System.IO.Stream
    member GetRequestStream : System.Net.TransportContext -> System.IO.Stream
    member GetResponse : unit -> System.Net.WebResponse
    member HaveResponse : bool
    member Headers : System.Net.WebHeaderCollection with get, set
    member IfModifiedSince : System.DateTime with get, set
    member KeepAlive : bool with get, set
    member MaximumAutomaticRedirections : int with get, set
    member MaximumResponseHeadersLength : int with get, set
    member MediaType : string with get, set
    member Method : string with get, set
    member Pipelined : bool with get, set
    member PreAuthenticate : bool with get, set
    member ProtocolVersion : System.Version with get, set
    member Proxy : System.Net.IWebProxy with get, set
    member ReadWriteTimeout : int with get, set
    member Referer : string with get, set
    member RequestUri : System.Uri
    member SendChunked : bool with get, set
    member ServicePoint : System.Net.ServicePoint
    member Timeout : int with get, set
    member TransferEncoding : string with get, set
    member UnsafeAuthenticatedConnectionSharing : bool with get, set
    member UseDefaultCredentials : bool with get, set
    member UserAgent : string with get, set
    static member DefaultCachePolicy : System.Net.Cache.RequestCachePolicy with get, set
    static member DefaultMaximumErrorResponseLength : int with get, set
    static member DefaultMaximumResponseHeadersLength : int with get, set
  end

Full name: System.Net.HttpWebRequest

  type: HttpWebRequest
  implements: Runtime.Serialization.ISerializable
  inherits: WebRequest
  inherits: MarshalByRefObject
Multiple overloads
WebRequest.Create(requestUri: Uri) : WebRequest
WebRequest.Create(requestUriString: string) : WebRequest
type Uri =
  class
    new : string -> System.Uri
    new : string * bool -> System.Uri
    new : string * System.UriKind -> System.Uri
    new : System.Uri * string -> System.Uri
    new : System.Uri * string * bool -> System.Uri
    new : System.Uri * System.Uri -> System.Uri
    member AbsolutePath : string
    member AbsoluteUri : string
    member Authority : string
    member DnsSafeHost : string
    member Equals : obj -> bool
    member Fragment : string
    member GetComponents : System.UriComponents * System.UriFormat -> string
    member GetHashCode : unit -> int
    member GetLeftPart : System.UriPartial -> string
    member Host : string
    member HostNameType : System.UriHostNameType
    member IsAbsoluteUri : bool
    member IsBaseOf : System.Uri -> bool
    member IsDefaultPort : bool
    member IsFile : bool
    member IsLoopback : bool
    member IsUnc : bool
    member IsWellFormedOriginalString : unit -> bool
    member LocalPath : string
    member MakeRelative : System.Uri -> string
    member MakeRelativeUri : System.Uri -> System.Uri
    member OriginalString : string
    member PathAndQuery : string
    member Port : int
    member Query : string
    member Scheme : string
    member Segments : string []
    member ToString : unit -> string
    member UserEscaped : bool
    member UserInfo : string
    static val UriSchemeFile : string
    static val UriSchemeFtp : string
    static val UriSchemeGopher : string
    static val UriSchemeHttp : string
    static val UriSchemeHttps : string
    static val UriSchemeMailto : string
    static val UriSchemeNews : string
    static val UriSchemeNntp : string
    static val UriSchemeNetTcp : string
    static val UriSchemeNetPipe : string
    static val SchemeDelimiter : string
    static member CheckHostName : string -> System.UriHostNameType
    static member CheckSchemeName : string -> bool
    static member Compare : System.Uri * System.Uri * System.UriComponents * System.UriFormat * System.StringComparison -> int
    static member EscapeDataString : string -> string
    static member EscapeUriString : string -> string
    static member FromHex : char -> int
    static member HexEscape : char -> string
    static member HexUnescape : string * int -> char
    static member IsHexDigit : char -> bool
    static member IsHexEncoding : string * int -> bool
    static member IsWellFormedUriString : string * System.UriKind -> bool
    static member TryCreate : string * System.UriKind * System.Uri -> bool
    static member TryCreate : System.Uri * string * System.Uri -> bool
    static member TryCreate : System.Uri * System.Uri * System.Uri -> bool
    static member UnescapeDataString : string -> string
  end

Full name: System.Uri

  type: Uri
  implements: Runtime.Serialization.ISerializable
val resp : WebResponse

  type: WebResponse
  implements: Runtime.Serialization.ISerializable
  implements: IDisposable
  inherits: MarshalByRefObject
member WebRequest.AsyncGetResponse : unit -> Async<WebResponse>
val stream : Stream

  type: Stream
  implements: IDisposable
  inherits: MarshalByRefObject
WebResponse.GetResponseStream() : Stream
val reader : StreamReader

  type: StreamReader
  implements: IDisposable
  inherits: TextReader
  inherits: MarshalByRefObject
type StreamReader =
  class
    inherit System.IO.TextReader
    new : System.IO.Stream -> System.IO.StreamReader
    new : System.IO.Stream * bool -> System.IO.StreamReader
    new : System.IO.Stream * System.Text.Encoding -> System.IO.StreamReader
    new : System.IO.Stream * System.Text.Encoding * bool -> System.IO.StreamReader
    new : System.IO.Stream * System.Text.Encoding * bool * int -> System.IO.StreamReader
    new : string -> System.IO.StreamReader
    new : string * bool -> System.IO.StreamReader
    new : string * System.Text.Encoding -> System.IO.StreamReader
    new : string * System.Text.Encoding * bool -> System.IO.StreamReader
    new : string * System.Text.Encoding * bool * int -> System.IO.StreamReader
    member BaseStream : System.IO.Stream
    member Close : unit -> unit
    member CurrentEncoding : System.Text.Encoding
    member DiscardBufferedData : unit -> unit
    member EndOfStream : bool
    member Peek : unit -> int
    member Read : unit -> int
    member Read : char [] * int * int -> int
    member ReadLine : unit -> string
    member ReadToEnd : unit -> string
    static val Null : System.IO.StreamReader
  end

Full name: System.IO.StreamReader

  type: StreamReader
  implements: IDisposable
  inherits: TextReader
  inherits: MarshalByRefObject
member StreamReader.AsyncReadToEnd : unit -> Async<string>
val getTotalLength : string list -> Async<int>

Full name: Untitled.getTotalLength

Download specified pages and add their lengths
val urls : string list

  type: string list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<string>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<string>
  implements: Collections.IEnumerable
val texts : string []

  type: string []
  implements: ICloneable
  implements: Collections.IList
  implements: Collections.ICollection
  implements: Collections.Generic.IList<string>
  implements: Collections.Generic.ICollection<string>
  implements: seq<string>
  implements: Collections.IEnumerable
  inherits: Array
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------

type List<'T> =
  | ( [] )
  | ( :: ) of 'T * 'T list
  with
    interface Collections.IEnumerable
    interface Collections.Generic.IEnumerable<'T>
    member Head : 'T
    member IsEmpty : bool
    member Item : index:int -> 'T with get
    member Length : int
    member Tail : 'T list
    static member Cons : head:'T * tail:'T list -> 'T list
    static member Empty : 'T list
  end

Full name: Microsoft.FSharp.Collections.List<_>

  type: List<'T>
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<'T>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<'T>
  implements: Collections.IEnumerable
val map : ('T -> 'U) -> 'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.map
Multiple items
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>

--------------------

type Async
with
  static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
  static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
  static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
  static member AwaitWaitHandle : waitHandle:Threading.WaitHandle * ?millisecondsTimeout:int -> Async<bool>
  static member CancelDefaultToken : unit -> unit
  static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
  static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
  static member Ignore : computation:Async<'T> -> Async<unit>
  static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
  static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
  static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:Threading.CancellationToken -> 'T
  static member Sleep : millisecondsDueTime:int -> Async<unit>
  static member Start : computation:Async<unit> * ?cancellationToken:Threading.CancellationToken -> unit
  static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
  static member StartImmediate : computation:Async<unit> * ?cancellationToken:Threading.CancellationToken -> unit
  static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:Threading.CancellationToken -> unit
  static member SwitchToContext : syncContext:Threading.SynchronizationContext -> Async<unit>
  static member SwitchToNewThread : unit -> Async<unit>
  static member SwitchToThreadPool : unit -> Async<unit>
  static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
  static member CancellationToken : Async<Threading.CancellationToken>
  static member DefaultCancellationToken : Threading.CancellationToken
end

Full name: Microsoft.FSharp.Control.Async
static member Async.Parallel : computations:seq<Async<'T>> -> Async<'T []>
module Seq

from Microsoft.FSharp.Collections
val sumBy : ('T -> 'U) -> seq<'T> -> 'U (requires member ( + ) and member get_Zero)

Full name: Microsoft.FSharp.Collections.Seq.sumBy
type String =
  class
    new : char -> string
    new : char * int * int -> string
    new : System.SByte -> string
    new : System.SByte * int * int -> string
    new : System.SByte * int * int * System.Text.Encoding -> string
    new : char [] * int * int -> string
    new : char [] -> string
    new : char * int -> string
    member Chars : int -> char
    member Clone : unit -> obj
    member CompareTo : obj -> int
    member CompareTo : string -> int
    member Contains : string -> bool
    member CopyTo : int * char [] * int * int -> unit
    member EndsWith : string -> bool
    member EndsWith : string * System.StringComparison -> bool
    member EndsWith : string * bool * System.Globalization.CultureInfo -> bool
    member Equals : obj -> bool
    member Equals : string -> bool
    member Equals : string * System.StringComparison -> bool
    member GetEnumerator : unit -> System.CharEnumerator
    member GetHashCode : unit -> int
    member GetTypeCode : unit -> System.TypeCode
    member IndexOf : char -> int
    member IndexOf : string -> int
    member IndexOf : char * int -> int
    member IndexOf : string * int -> int
    member IndexOf : string * System.StringComparison -> int
    member IndexOf : char * int * int -> int
    member IndexOf : string * int * int -> int
    member IndexOf : string * int * System.StringComparison -> int
    member IndexOf : string * int * int * System.StringComparison -> int
    member IndexOfAny : char [] -> int
    member IndexOfAny : char [] * int -> int
    member IndexOfAny : char [] * int * int -> int
    member Insert : int * string -> string
    member IsNormalized : unit -> bool
    member IsNormalized : System.Text.NormalizationForm -> bool
    member LastIndexOf : char -> int
    member LastIndexOf : string -> int
    member LastIndexOf : char * int -> int
    member LastIndexOf : string * int -> int
    member LastIndexOf : string * System.StringComparison -> int
    member LastIndexOf : char * int * int -> int
    member LastIndexOf : string * int * int -> int
    member LastIndexOf : string * int * System.StringComparison -> int
    member LastIndexOf : string * int * int * System.StringComparison -> int
    member LastIndexOfAny : char [] -> int
    member LastIndexOfAny : char [] * int -> int
    member LastIndexOfAny : char [] * int * int -> int
    member Length : int
    member Normalize : unit -> string
    member Normalize : System.Text.NormalizationForm -> string
    member PadLeft : int -> string
    member PadLeft : int * char -> string
    member PadRight : int -> string
    member PadRight : int * char -> string
    member Remove : int -> string
    member Remove : int * int -> string
    member Replace : char * char -> string
    member Replace : string * string -> string
    member Split : char [] -> string []
    member Split : char [] * int -> string []
    member Split : char [] * System.StringSplitOptions -> string []
    member Split : string [] * System.StringSplitOptions -> string []
    member Split : char [] * int * System.StringSplitOptions -> string []
    member Split : string [] * int * System.StringSplitOptions -> string []
    member StartsWith : string -> bool
    member StartsWith : string * System.StringComparison -> bool
    member StartsWith : string * bool * System.Globalization.CultureInfo -> bool
    member Substring : int -> string
    member Substring : int * int -> string
    member ToCharArray : unit -> char []
    member ToCharArray : int * int -> char []
    member ToLower : unit -> string
    member ToLower : System.Globalization.CultureInfo -> string
    member ToLowerInvariant : unit -> string
    member ToString : unit -> string
    member ToString : System.IFormatProvider -> string
    member ToUpper : unit -> string
    member ToUpper : System.Globalization.CultureInfo -> string
    member ToUpperInvariant : unit -> string
    member Trim : unit -> string
    member Trim : char [] -> string
    member TrimEnd : char [] -> string
    member TrimStart : char [] -> string
    static val Empty : string
    static member Compare : string * string -> int
    static member Compare : string * string * bool -> int
    static member Compare : string * string * System.StringComparison -> int
    static member Compare : string * string * System.Globalization.CultureInfo * System.Globalization.CompareOptions -> int
    static member Compare : string * string * bool * System.Globalization.CultureInfo -> int
    static member Compare : string * int * string * int * int -> int
    static member Compare : string * int * string * int * int * bool -> int
    static member Compare : string * int * string * int * int * System.StringComparison -> int
    static member Compare : string * int * string * int * int * System.Globalization.CultureInfo * System.Globalization.CompareOptions -> int
    static member Compare : string * int * string * int * int * bool * System.Globalization.CultureInfo -> int
    static member CompareOrdinal : string * string -> int
    static member CompareOrdinal : string * int * string * int * int -> int
    static member Concat : obj -> string
    static member Concat : obj [] -> string
    static member Concat : string [] -> string
    static member Concat : obj * obj -> string
    static member Concat : string * string -> string
    static member Concat : obj * obj * obj -> string
    static member Concat : string * string * string -> string
    static member Concat : obj * obj * obj * obj -> string
    static member Concat : string * string * string * string -> string
    static member Copy : string -> string
    static member Equals : string * string -> bool
    static member Equals : string * string * System.StringComparison -> bool
    static member Format : string * obj -> string
    static member Format : string * obj [] -> string
    static member Format : string * obj * obj -> string
    static member Format : System.IFormatProvider * string * obj [] -> string
    static member Format : string * obj * obj * obj -> string
    static member Intern : string -> string
    static member IsInterned : string -> string
    static member IsNullOrEmpty : string -> bool
    static member Join : string * string [] -> string
    static member Join : string * string [] * int * int -> string
  end

Full name: System.String

  type: String
  implements: IComparable
  implements: ICloneable
  implements: IConvertible
  implements: IComparable<string>
  implements: seq<char>
  implements: Collections.IEnumerable
  implements: IEquatable<string>
val length : string -> int

Full name: Microsoft.FSharp.Core.String.length
async {
  let req = HttpWebRequest.Create(Uri(url))
  let! resp = req.AsyncGetResponse()
  let stream = resp.GetResponseStream()
  let reader = new StreamReader(stream)
  return! reader.AsyncReadToEnd() }

Published: Monday, 18 October 2010, 1:42 AM
Tags: functional, f#
Read the complete article

All blog posts by tag

f# (112), functional (66), research (44), c# (37), asynchronous (27), parallel (23), academic (22), functional programming (20), universe (20), programming languages (18), meta-programming (18), philosophy (15), links (15), presentations (14), data science (12), writing (12), joinads (12), thegamma (11), web (10), data journalism (9), math and numerics (9), random thoughts (9), talks (8), phalanger (8), haskell (7), mono (7), webcast (7), fslab (5), open source (5), visualization (4), fun (4), accelerator (4), design (3), type providers (3), linq (3), f# data (3), .net (3), training (2), coeffects (2), deedle (2), monads (2), art (2), fractals (2), funscript (2), new york (2), manning (2), books (2), teaching (1), fable (1), machine learning (1), comonads (1), fake (1), f# formatting (1), deep dives (1), async (1), events (1), trainings (1), london (1), literate (1)