9 people like it.

A Computation Expression wrapper for StringBuilder

A bit of syntax eye candy for your string building code.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
open System

type StringBuilder = B of (Text.StringBuilder -> unit)

let build (B f) =
    let b = new Text.StringBuilder()
    do f b
    b.ToString ()

type StringBuilderM () =
    let (!) = function B f -> f
    member __.Yield (txt : string) = B(fun b -> b.Append txt |> ignore)
    member __.Yield (c : char) = B(fun b -> b.Append c |> ignore)
//    member __.Yield (o : obj) = B(fun b -> b.Append o |> ignore)
    member __.YieldFrom f = f : StringBuilder

    member __.Combine(f,g) = B(fun b -> !f b; !g b)
    member __.Delay f = B(fun b -> !(f ()) b) : StringBuilder
    member __.Zero () = B(fun _ -> ())
    member __.For (xs : 'a seq, f : 'a -> StringBuilder) =
                    B(fun b ->
                        let e = xs.GetEnumerator ()
                        while e.MoveNext() do
                            !(f e.Current) b)
    member __.While (p : unit -> bool, f : StringBuilder) =
                    B(fun b -> while p () do !f b)

let string = new StringBuilderM ()
            
// example

let bytes2hex (bytes : byte []) =
    string {
        for byte in bytes -> sprintf "%02x" byte
    } |> build
namespace System
type StringBuilder = | B of (StringBuilder -> unit)

Full name: Script.StringBuilder
union case StringBuilder.B: (Text.StringBuilder -> unit) -> StringBuilder
namespace System.Text
Multiple items
type StringBuilder =
  new : unit -> StringBuilder + 5 overloads
  member Append : value:string -> StringBuilder + 18 overloads
  member AppendFormat : format:string * arg0:obj -> StringBuilder + 4 overloads
  member AppendLine : unit -> StringBuilder + 1 overload
  member Capacity : int with get, set
  member Chars : int -> char with get, set
  member Clear : unit -> StringBuilder
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EnsureCapacity : capacity:int -> int
  member Equals : sb:StringBuilder -> bool
  ...

Full name: System.Text.StringBuilder

--------------------
Text.StringBuilder() : unit
Text.StringBuilder(capacity: int) : unit
Text.StringBuilder(value: string) : unit
Text.StringBuilder(value: string, capacity: int) : unit
Text.StringBuilder(capacity: int, maxCapacity: int) : unit
Text.StringBuilder(value: string, startIndex: int, length: int, capacity: int) : unit
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val build : StringBuilder -> string

Full name: Script.build
val f : (Text.StringBuilder -> unit)
val b : Text.StringBuilder
Text.StringBuilder.ToString() : string
Text.StringBuilder.ToString(startIndex: int, length: int) : string
Multiple items
type StringBuilderM =
  new : unit -> StringBuilderM
  member Combine : f:StringBuilder * g:StringBuilder -> StringBuilder
  member Delay : f:(unit -> StringBuilder) -> StringBuilder
  member For : xs:seq<'a> * f:('a -> StringBuilder) -> StringBuilder
  member While : p:(unit -> bool) * f:StringBuilder -> StringBuilder
  member Yield : txt:string -> StringBuilder
  member Yield : c:char -> StringBuilder
  member YieldFrom : f:StringBuilder -> StringBuilder
  member Zero : unit -> StringBuilder

Full name: Script.StringBuilderM

--------------------
new : unit -> StringBuilderM
member StringBuilderM.Yield : txt:string -> StringBuilder

Full name: Script.StringBuilderM.Yield
val txt : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
Text.StringBuilder.Append(value: char []) : Text.StringBuilder
   (+0 other overloads)
Text.StringBuilder.Append(value: obj) : Text.StringBuilder
   (+0 other overloads)
Text.StringBuilder.Append(value: uint64) : Text.StringBuilder
   (+0 other overloads)
Text.StringBuilder.Append(value: uint32) : Text.StringBuilder
   (+0 other overloads)
Text.StringBuilder.Append(value: uint16) : Text.StringBuilder
   (+0 other overloads)
Text.StringBuilder.Append(value: decimal) : Text.StringBuilder
   (+0 other overloads)
Text.StringBuilder.Append(value: float) : Text.StringBuilder
   (+0 other overloads)
Text.StringBuilder.Append(value: float32) : Text.StringBuilder
   (+0 other overloads)
Text.StringBuilder.Append(value: int64) : Text.StringBuilder
   (+0 other overloads)
Text.StringBuilder.Append(value: int) : Text.StringBuilder
   (+0 other overloads)
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val __ : StringBuilderM
member StringBuilderM.Yield : c:char -> StringBuilder

Full name: Script.StringBuilderM.Yield
val c : char
Multiple items
val char : value:'T -> char (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.char

--------------------
type char = Char

Full name: Microsoft.FSharp.Core.char
member StringBuilderM.YieldFrom : f:StringBuilder -> StringBuilder

Full name: Script.StringBuilderM.YieldFrom
val f : StringBuilder
member StringBuilderM.Combine : f:StringBuilder * g:StringBuilder -> StringBuilder

Full name: Script.StringBuilderM.Combine
val g : StringBuilder
member StringBuilderM.Delay : f:(unit -> StringBuilder) -> StringBuilder

Full name: Script.StringBuilderM.Delay
val f : (unit -> StringBuilder)
member StringBuilderM.Zero : unit -> StringBuilder

Full name: Script.StringBuilderM.Zero
member StringBuilderM.For : xs:seq<'a> * f:('a -> StringBuilder) -> StringBuilder

Full name: Script.StringBuilderM.For
val xs : seq<'a>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val f : ('a -> StringBuilder)
val e : Collections.Generic.IEnumerator<'a>
Collections.Generic.IEnumerable.GetEnumerator() : Collections.Generic.IEnumerator<'a>
Collections.IEnumerator.MoveNext() : bool
property Collections.Generic.IEnumerator.Current: 'a
member StringBuilderM.While : p:(unit -> bool) * f:StringBuilder -> StringBuilder

Full name: Script.StringBuilderM.While
val p : (unit -> bool)
type bool = Boolean

Full name: Microsoft.FSharp.Core.bool
Multiple items
val string : StringBuilderM

Full name: Script.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
val bytes2hex : bytes:byte [] -> string

Full name: Script.bytes2hex
val bytes : byte []
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.byte

--------------------
type byte = Byte

Full name: Microsoft.FSharp.Core.byte
Multiple items
val byte : byte

--------------------
type byte = Byte

Full name: Microsoft.FSharp.Core.byte
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf

More information

Link:http://fssnip.net/d5
Posted:4 years ago
Author:Eirik Tsarpalis
Tags: computation expressions , stringbuilder