how can I build a format string with sprintf, in F#? - f#

I'm trying to go from:
sprintf "%3.1f" myNumber
to:
sprintf myFormatter myNumber
which is not possible
I have a situation where number precision depends on some settings, so I would like to be able to create my own formatter string.
I know it can be done with String.Format, but I am curious if there is a F# way with sprintf, or ksprinf; can it be done?

Simple answer
EDIT: Diego Esmerio on F# Slack showed me a simpler way that I honestly never thought of while working out the answer below. The trick is to use PrintfFormat directly, like as follows.
// Credit: Diego. This
let formatPrec precision =
PrintfFormat<float -> string,unit,string,string>(sprintf "%%1.%if" precision)
let x = 15.234
let a = sprintf (formatPrec 0) x
let b = sprintf (formatPrec 1) x
let c = sprintf (formatPrec 3) x
Output:
val formatPrec : precision:int -> PrintfFormat<(float -> string),unit,string,string>
val x : float = 15.234
val a : string = "15"
val b : string = "15.2"
val c : string = "15.234"
This approach is arguably much simpler than the Expr-based approach below. For both approaches, be careful with the formatting string, as it will compile just fine, but break at runtime if it is invalid.
Original answer (complex)
This isn't trivial to do, because functions like sprintf and printfn are compile-time special-case functions that turn your string-argument into a function (in this case of type float -> string).
There are some things you can do with kprintf, but it won't allow the formatting-argument to become a dynamic value, since the compiler still wants to type-check that.
However, using quotations we can build such function ourselves. The easy way is to create quotation from your expression and to change the parts we need to change.
The starting point is this:
> <# sprintf "%3.1f" #>
val it : Expr<(float -> string)> =
Let (clo1,
Call (None, PrintFormatToString,
[Coerce (NewObject (PrintfFormat`5, Value ("%3.1f")), PrintfFormat`4)]),
Lambda (arg10, Application (clo1, arg10)))
...
That may look like a whole lot of mess, but since we only need to change one tiny bit, we can do this rather simply:
open Microsoft.FSharp.Quotations // part of F#
open Microsoft.FSharp.Quotations.Patterns // part of F#
open FSharp.Quotations.Evaluator // NuGet package (with same name)
// this is the function that in turn will create a function dynamically
let withFormat format =
let expr =
match <# sprintf "%3.1f" #> with
| Let(var, expr1, expr2) ->
match expr1 with
| Call(None, methodInfo, [Coerce(NewObject(ctor, [Value _]), mprintFormat)]) ->
Expr.Let(var, Expr.Call(methodInfo, [Expr.Coerce(Expr.NewObject(ctor, [Expr.Value format]), mprintFormat)]), expr2)
| _ -> failwith "oops" // won't happen
| _ -> failwith "oops" // won't happen
expr.CompileUntyped() :?> (float -> string)
To use this, we can now simply do this:
> withFormat "%1.2f" 123.4567899112233445566;;
val it : string = "123.46"
> withFormat "%1.5f" 123.4567899112233445566;;
val it : string = "123.45679"
> withFormat "%1.12f" 123.4567899112233445566;;
val it : string = "123.456789911223"
Or like this:
> let format = "%0.4ef";;
val format : string = "%0.4ef"
> withFormat format 123.4567899112233445566;;
val it : string = "1.2346e+002f"
It doesn't matter whether the format string is now a fixed string during compile time. However, if this is used in performance sensitive area, you may want to cache the resulting functions, as recompiling an expression tree is moderately expensive.

Related

A function that accepts multiple types

I am fairly new to f#, but I want to know if it is possible to make a function that accepts multiple types of variables.
let add x y = x + y
let integer = add 1 2
let word = add "He" "llo"
Once a function use a type of variable it cannot accept another one.
You need to read about statically resolved type parameters and inline functions. It allows to create functions which may take any type that supports operation and/or have member. So your add function should be defined this way:
let inline add x y = x + y
Don't overuse inlined functions because their code inlined in call site and may increase assembly size, but may increase performance (test each case, don't make predictions!). Also inlined function are supported only by F# compiler and may not work with other languages (important when designing libraries).
Example of SRTP magic:
let inline (|Parsed|_|) (str: string) =
let mutable value = Unchecked.defaultof<_>
let parsed = ( ^a : (static member TryParse : string * byref< ^a> -> bool) (str, &value))
if parsed then
Some value
else
None
match "123.3" with
| Parsed 123 -> printfn "int 123"
| Parsed 123.4m -> printfn "decimal 123.4"
| Parsed 123.3 -> printfn "double 123.3"
// | Parsed "123.3" -> printfn "string 123.3" // compile error because string don't have TryParse static member
| s -> printfn "unmatched %s" s

Dynamic Lookup in F#

Can somebody help me with article of Tomas Petricek: http://tomasp.net/blog/fsharp-dynamic-lookup.aspx/#dynfslinks?
The problem is that it is severely outdated. I understand that namespaces
open Microsoft.FSharp.Quotations.Typed
open Microsoft.FSharp.Quotations.Raw
are gone. So I removed the openings. But there are still errors. "Typed" is not defined. "RecdGet" is not defined. And I suspect they are not the last. I'm trying to prove to my boss that F# is good to use for database normalization. Dynamic lookup of fields would really helped me to deal with similarly named fields having different prefixes.
There is also post of Tomas on fpish: https://fpish.net/topic/None/57493, which I understand predates the article
Here's a rough equivalent:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
type DynamicMember<'t,'u> = Expr<'t -> 'u>
let getValueReader (expr:DynamicMember<'recdT, 'fieldT>) =
// Match the quotation representing the symbol
match expr with
| Lambda(v, PropertyGet (Some (Var v'), pi, [])) when v = v' ->
// It represents reading of the F# record field..
// .. get a function that reads the record field using F# reflection
let rdr = Reflection.FSharpValue.PreComputeRecordFieldReader pi
// we're not adding any additional processing, so we just
// simply add type conversion to the correct types & return it
((box >> rdr >> unbox) : 'recdT -> 'fieldT)
| _ ->
// Quotation doesn't represent symbol - this is an error
failwith "Invalid expression - not reading record field!"
type SampleRec = { Str : string; Num : int }
let readStrField = getValueReader <# fun (r : SampleRec) -> r.Str #>
let readNumField = getValueReader <# fun (r : SampleRec) -> r.Num #>
let rc = { Str = "Hello world!"; Num = 42 }
let s, n = readStrField rc, readNumField rc
printfn "Extracted: %s, %d" s n

How to manage debug printing in F#

I want to add debug printing to my project with a function having a type signature something like:
bool -> Printf.TextWriterFormat<'a> -> 'a
i.e. it should take a bool indicating whether or not we are in verbose mode, and use that to take the decision about whether to print or not.
For example, lets say dprint : bool -> Printf.TextWriterFormat<'a> -> 'a then I would like this behaviour:
> dprint true "Hello I'm %d" 52;;
Hello I'm 52
val it : unit = ()
> dprint false "Hello I'm %d" 52;;
val it : unit = ()
The idea is that a command line flag can be used to avoid control this output. I also want to avoid a runtime cost in the "not verbose" case. It is possible to define a function that works like this using kprintf:
let dprint (v: bool) (fmt: Printf.StringFormat<'a,unit>) =
let printVerbose (s: string) =
if v then System.Console.WriteLine(s)
fmt |> Printf.kprintf printVerbose
but printing/ignoring a sequence of numbers with List.iter (dprint b "%A") [1..10000] (b \in {true,false}) takes amount 1.5s for both values of b on my machine.
I came up with another method using reflection that builds an appropriately typed function to discard the formatting arguments:
let dprint (v: bool) (fmt: Printf.TextWriterFormat<'a>) : 'a =
let rec mkKn (ty: System.Type) =
if FSharpType.IsFunction(ty) then
let _, ran = FSharpType.GetFunctionElements(ty)
FSharpValue.MakeFunction(ty,(fun _ -> mkKn ran))
else
box ()
if v then
printfn fmt
else
unbox<'a> (mkKn typeof<'a>)
but here the reflection seems too expensive (even more so than that done inside the standard libraries complicated definition of printf sometimes).
I don't want to litter my code with things like:
if !Options.verbose then
printfn "Debug important value: %A" bigObject5
or closures:
dprint (fun () -> printfn "Debug important value: %A" bigObject5)
so, are there any other solutions?
I like your solution using reflection. How about caching it on the type level so that you pay the price of reflection only once per type? For example:
let rec mkKn (ty: System.Type) =
if Reflection.FSharpType.IsFunction(ty) then
let _, ran = Reflection.FSharpType.GetFunctionElements(ty)
// NOTICE: do not delay `mkKn` invocation until runtime
let f = mkKn ran
Reflection.FSharpValue.MakeFunction(ty, fun _ -> f)
else
box ()
[<Sealed>]
type Format<'T> private () =
static let instance : 'T =
unbox (mkKn typeof<'T>)
static member Instance = instance
let inline dprint verbose args =
if verbose then
printfn args
else
Format<_>.Instance
A pragmatist would just use the fast C# formatted printing machinery instead of this. I avoid Printf functions in production code because of the overhead they have, as you point out. But then F# printing definitely feels nicer to use.
My #time results for List.iter (dprint false "%A") [1..10000]:
Original version : 0.85
Original version with reflection : 0.27
The proposed version : 0.03
How about this:
/// Prints a formatted string to DebugListeners.
let inline dprintfn fmt =
Printf.ksprintf System.Diagnostics.Debug.WriteLine fmt
Then you can write:
dprintfn "%s %s" "Hello" "World!"
Debug.WriteLine(...) is marked with [<Conditional("DEBUG")>] so the F# compiler should be able to eliminate the entire statement at compile-time (though you'll have to experiment and check the compiled IL to see if it actually does.
Note that this solution only works if you don't care about changing the verbosity at run-time. If that's the case, you'll have to look for a different solution.
UPDATE : Out of curiousity, I just tried this code (it does work) and the F# 2.0 compiler doesn't compile everything away (even with optimizations on), so the speed is the same whether debugging or not. There might be other ways to get the compiler to eliminate the whole statement to fix the speed issue, but you'll just have to experiment a bit to find out.
Why not use #defines just do
let dprint (fmt: Printf.StringFormat<'a,unit>) =
#if DEBUG
let printVerbose (s: string) =
System.Console.WriteLine(s)
fmt |> Printf.kprintf printVerbose
#else
fun _ -> ()
On my machine the sample test takes 0.002s in the optimised version

F# type constraints and overloading resolution

I am trying to emulate a system of type classes in F#; I would like to create pair printer which automatically instantiates the right series of calls to the printing functions. My latest try, which is pasted here, fails miserably since F# cannot identify the right overload and gives up immediately:
type PrintableInt(x:int) =
member this.Print() = printfn "%d" x
let (!) x = PrintableInt(x)
type Printer() =
static member inline Print< ^a when ^a : (member Print : Unit -> Unit)>(x : ^a) =
(^a : (member Print : Unit -> Unit) x)
static member inline Print((x,y) : 'a * 'b) =
Printer.Print(x)
Printer.Print(y)
let x = (!1,!2),(!3,!4)
Printer.Print(x)
Is there any way to do so? I am doing this in the context of game development, so I cannot afford the runtime overhead of reflection, retyping and dynamic casting: either I do this statically through inlining or I don't do it at all :(
What you're trying to do is possible.
You can emulate typeclasses in F#, as Tomas said maybe is not as idiomatic as in Haskell. I think in your example you are mixing typeclasses with duck-typing, if you want to go for the typeclasses approach don't use members, use functions and static members instead.
So your code could be something like this:
type Print = Print with
static member ($) (_Printable:Print, x:string) = printfn "%s" x
static member ($) (_Printable:Print, x:int ) = printfn "%d" x
// more overloads for existing types
let inline print p = Print $ p
type Print with
static member inline ($) (_Printable:Print, (a,b) ) = print a; print b
print 5
print ((10,"hi"))
print (("hello",20), (2,"world"))
// A wrapper for Int (from your sample code)
type PrintableInt = PrintableInt of int with
static member ($) (_Printable:Print, (PrintableInt (x:int))) = printfn "%d" x
let (!) x = PrintableInt(x)
let x = (!1,!2),(!3,!4)
print x
// Create a type
type Person = {fstName : string ; lstName : string } with
// Make it member of _Printable
static member ($) (_Printable:Print, p:Person) = printfn "%s, %s" p.lstName p.fstName
print {fstName = "John"; lstName = "Doe" }
print (1 ,{fstName = "John"; lstName = "Doe" })
Note: I used an operator to avoid writing the constraints by hand, but in this case is also possible to use a named static member.
More about this technique here.
What you're trying to do is not possible (edit: apparently, it can be done - but it might not be idiomatic F#), because the constraint language cannot capture the constraints you need for the second Print operation. Basically, there is no way to write recursive constraints saying that:
Let C be a constraint specifying that the type either provides Print or it is a two-element tuple where each element satisfies C.
F# does not support type-classes and so most of the attempts to emulate them will (probably) be limited in some way or will look very unnatural. In practice, instead of trying to emulate solutions that work in other languages, it is better to look for an idiomatic F# solution to the problem.
The pretty printing that you're using as a sample would be probably implemented using Reflection or by wrapping not just integers, but also tuples.

Working with Nullable<'T> in F#

I'm wondering what others have come up with for dealing with Nullable<'T> in F#. I want to use Nullable<'T> on data types so that serialization works properly (i.e., doesn't write out F# option type to XML). But, I don't want my code stuck dealing with the ugliness of dealing with Nullable<'T> directly. Any suggestions?
Is it better to use active patterns to match directly on Nullable, or just a converter to option and use Some/None matching?
Additionally, I'd love to hear ideas on dealing with nullable references in a nice manner too. If I use, say "string option", then I end up with the F# option type wrapping things. If I don't then I can't distinguish between truly optional strings and strings that shouldn't be null.
Any chance .NET 4 will take on an Option<'T> to help out? (If it's part of the BCL, then we might see better support for it...)
As active patterns as options plays nicely with pattern matching, but is seems by using active patterns (i.e. typeof and ??) your code will eat more ticks.
The base question is how you will deal with your nullable references?
In case your code is long chained computations it's nice to use monadic syntax:
type Maybe<'a> = (unit -> 'a option)
let succeed x : Maybe<'a> = fun () -> Some(x)
let fail : Maybe<'a> = fun () -> None
let run (a: Maybe<'a>) = a()
let bind p rest = match run p with None -> fail | Some r -> (rest r)
let delay f = fun () -> run (f ())
type MaybeBuilder() =
member this.Return(x) = succeed x
member this.Let(p,rest) = rest p
member this.Bind(p,rest) = bind p rest
member this.Delay(f) = delay f
let maybe = new MaybeBuilder()
let add (a:'a) (b:'a) =
maybe {
match TryGetNumericAssociation<'a>() with
| Some v -> return (v.Add(a,b))
| _ -> return! fail
}
let add3 (a:'a) (b:'a) (c:'a) =
maybe {
let! ab = add a b
let! abc = add ab c
return abc
}
> let r1 = add 1 2;;
val r1 : (unit -> int option)
> r1();;
val it : int option = Some 3
> let r2 = add "1" "2";;
val r2 : (unit -> string option)
> r2();;
val it : string option = None
> let r3 = add3 "one" "two" "three";;
val r3 : (unit -> string option)
> r3();;
val it : string option = None

Resources