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
Related
I'm using quite a lot this piece of code:
let inline (||>) (a: 'a option) (b: 'a -> unit) = if a.IsSome then b a.Value
so I can do things like
myData ||> DoSomethingWithIt
without having to test if myData is Some or None since there are many functions that don't generally need to test for an option. This avoid to put the test in the function itself.
I would like to extend this to methods of a type where I could do like C#'s:
myData?.DoSomethingWithIt
essentially replacing:
if myData.IsSome then myData.Value.DoSomethingWithIt
with some syntactic sugar.
but I have no idea how I could do the operator so that it allows to get access to the type's method in the expression. Is that possible in F#?
I'm also open to learn about why it could be a bad idea if it is :)
Depending on your return type of DoSomethingWithIt the F# library offers a few standard functions for working with Options that can be turned into operators.
let x = Some 1
let aPrinter a = printfn "%i" a
let add1 a = a + 1
let (|?>) opt f = Option.iter f opt
let (|??>) opt f = Option.map f opt
x |?> aPrinter
let y = x |??> add1
You can also consider redefining your DoSomethingWithIt to work with an option by partial application.
let DoSomethingWithIt' = Option.iter DoSomethingWithIt
let something' = Option.iter (fun (b:B) -> b.DoSomethingWithIt()) //For instance methods
That may end up being a lot of work depending how many functions you are dealing with.
Ultimately you shouldn't try to hide the fact you are working with Options. By making something an Option you are telling the compiler that you aren't sure whether it exists or not. It is trying to help you by forcing you to deal with the None case. If there are lots of cases in your code where you know your Option is Some then there's probably a larger architectural issue in your code and you should try to lift all your Option<'T> to just T prior to doing work with them. e.g.:
let lift xs =
[
for x in xs do
match x with
| Some x -> yield x
| None -> ()
]
Have a look at Option.iter. It has the same signature as your operator.
There is no analogical syntax for such constructions but F# have alternatives.
The easiest way is to use FSharpx.Extras library and FSharpx.Option.maybe computation expression which will allow you to use Option related operations.
open FSharpx.Option
let a = Some 1
let b = maybe {
let! v = a
return v + 3
} // b is (Some 4)
let c : int option = None
let d = maybe {
let! v = c
return v + 3 // this line won't be reached
} // d is None
I believe that the ?. operator in c# is a syntactic sugar that hides the if statement checking for null before invoking a member of the type. Even if you could make it work the way you plan, I feel that it would go against the FP principles and could cause more problems down the line.
The Option module contains probably most of what you need already. The iter function allows to call a function on the value of the Option if that value is present (Some).
If you have situation that your input parametes can be nulls, but not options, you can use the Option.ofObj function that will convert the parameter to an Option with Some if the parameter is not null, else None.
So assuming that your function DoSomethingWithit accepts a string and returns unit:
let DoSomethingWithIt = //(string -> unit)
printf "%s; "
You can use this more verbose syntax to (for example) iterate over nullable values in your list:
let lst = [ "data"; "data 2"; null; "data3" ]
lst
|> List.iter (fun v -> v |> Option.ofObj |> Option.iter DoSomethingWithIt)
Alternatively you can compose the Optioni.ofObj and Option.iter DoSomethingWithIt functions and do something like
let SafeDoSomethingWithIt = //(string -> unit)
Option.ofObj >> Option.iter DoSomethingWithIt
This gives you safe invocation:
let lst2 = [ "data"; "data 2"; null; "data3" ]
lst2
|> List.iter SafeDoSomethingWithIt
You can generalize the combination of the functions returning unit (but not only)
let makeSafe fn =
Option.ofObj >> Option.iter fn
Then you can create a series of safe functions:
let SafeDoSomethingWithIt = makeSafe DoSomethingWithIt
let safePrint = makeSafe (printf "%s; ")
//...etc
Then this still works:
lst2
|> List.iter SafeDoSomethingWithIt
lst2
|> List.iter safePrint
You can also write a wrapper for functions returning values using Option.bind function.
let makeSafeReturn fn = //(string -> string option)
Option.ofObj >> Option.bind fn
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.
I'm messing around in F# and tried to write a function that can take an int list or a string list. I have written a function that is logically generic, in that I can modify nothing but the type of the argument and it will run with both types of list. But I cannot generically define it to take both.
Here is my function, without type annotation:
let contains5 xs =
List.map int xs
|> List.contains 5
When I try to annotate the function to take a generic list, I receive a warning FS0064: the construct causes the code to be less generic than indicated by the type annotations. In theory I shouldn't need to annotate this to be generic, but I tried anyway.
I can compile this in two separate files, one with
let stringtest = contains5 ["1";"2";"3";"4"]
and another with
let inttest = contains5 [1;2;3;4;5]
In each of these files, compilation succeeds. Alternately, I can send the function definition and one of the tests to the interpreter, and type inference proceeds just fine. If I try to compile, or send to the interpreter, the function definition and both tests, I receive error FS0001: This expression was expected to have type string, but here has type int.
Am I misunderstanding how typing should work? I have a function whose code can handle a list of ints or a list of strings. I can successfully test it with either. But I can't use it in a program that handles both?
You are running into value restrictions on the automatic generalization of the type inference system as outlined here
Specifically,
Case 4: Adding type parameters.
The solution is to make your function generic rather than just making its parameters generic.
let inline contains5< ^T when ^T : (static member op_Explicit: ^T -> int) > (xs : ^T list) =
List.map int xs
|> List.contains 5
You have to make the function inline because you have to use a statically resolved type parameter, and you have to use a statically resolved type parameter in order to use member constraints to specify that the type must be convertible to an int. As outlined here
You can use inline to prevent the function from being fixed to a particular type.
In FSI, the interactive REPL:
> open System;;
> let inline contains5 xs = List.map int xs |> List.contains 5;;
val inline contains5 :
xs: ^a list -> bool when ^a : (static member op_Explicit : ^a -> int)
> [1;2;3] |> contains5;;
val it : bool = false
> ["1";"2";"5"] |> contains5;;
val it : bool = true
Note that the signature of contains5 has a generic element to it. There's more about inline functions here.
This is already answered correctly above, so I just wanted to chime in with why I think it's a good thing that F# appears to makes this difficult / forces us to lose type safety. Personally I don't see these as logically equivalent:
let inline contains5 xs = List.map int xs |> List.contains 5
let stringTest = ["5.00"; "five"; "5"; "-5"; "5,"]
let intTest = [1;2;3;4;5]
contains5 stringTest // OUTPUT: System.FormatException: Input string was not in a correct format.
contains5 intTest // OUTPUT: true
When inlined, the compiler would create two logically distinct versions of the function. When performed on the list<int> we get a boolean result. When performed on a list<string> we get a boolean result or an exception. I like that F# nudges me towards acknowledging this.
let maybeInt i =
match Int32.TryParse i with
| true,successfullyParsedInteger -> Some successfullyParsedInteger
| _ -> None
let contains5 xs =
match box xs with
| :? list<int> as ixs ->
ixs |> List.contains 5 |> Ok
| :? list<string> as sxs ->
let successList = sxs |> List.map maybeInt |> List.choose id
Ok (successList |> List.contains 5)
| _ ->
Error "Error - this function expects a list<int> or a list<string> but was passed something else."
let stringTest = ["5.00"; "five"; "5"; "-5"; "5,"]
let intTest = [1;2;3;4;5]
let result1 = contains5 stringTest // OUTPUT: Ok true
let result2 = contains5 intTest // OUTPUT: Ok true
Forces me to ask if some of the values in the string list cannot be parsed, should I drop out and fail, or should I just try and look for any match on any successful parse results?.
My approach above is horrible. I'd split the function that operates on the strings from the one that operates on the integers. I think your question was academic rather than a real use case though, so I hope I haven't gone off on too much of a tangent here!
Disclaimer: I'm a beginner, don't trust anything I say.
Why are parentheses needed on read_rest_of_csv below?
let read_rest_of_csv() =
csv_data.Add(csv_fileH.ReadFields()) |> ignore
not csv_fileH.EndOfData
while read_rest_of_csv() do ignore None
Without the parentheses, the loop will not terminate.
open System
open System.Threading
open System.Collections.Generic
open System.Linq
open System.Text
open System.Threading.Tasks
open System.IO
open Microsoft.VisualBasic.FileIO
[<EntryPoint>]
let main argv =
let csv_fileH = new TextFieldParser("test1.csv")
csv_fileH.TextFieldType = FieldType.Delimited |> ignore
let x = csv_fileH.SetDelimiters(",")
let csv_data = new List<string[]>()
let eod = csv_fileH.EndOfData
if not eod then
let column_headings = csv_fileH.ReadFields()
csv_data.Add(column_headings) |> ignore
let read_rest_of_csv =
csv_data.Add(csv_fileH.ReadFields()) |> ignore
not csv_fileH.EndOfData
while read_rest_of_csv do ignore None
0
I apologize that I cannot remember where I saw this. I think it was in SO. It's a nice example.
Could this be that without parens I'm dealing with a function object of sorts?
I am indeed coming from not only a C, C++, and C# background, but also an intermediate Clojure background as well. In my case with F# syntax, reading my Haskell manual in a little more detail might have helped, because the syntaxes seem similar.
It seems that people coming from C-family languages (C#, Java, C, C++, JavaScript) are having problems understanding the use of brackets in F#. I certainly had, and it took me some years learning how things work.
In a nutshell, the most basic building block in F# is a value. Values can be let-bound:
let foo = bar
This means that foo is a value, which happens to be equal to bar.
Functions are also values:
// 'a -> 'a * 'a
let f = fun x -> x, x
Here, f is a function that takes some value (x) and returns a tuple with x as both the first and the second element.
That's a bit cumbersome to write, so there's a shorthand for that:
// 'a -> 'a * 'a
let f x = x, x
Notice that there are no brackets in these expressions.
Sometimes you need to adjust the precedence of operators. Just like in maths, 1 + 2 * 3 (which is equivalent to 1 + (2 * 3)) isn't the same as (1 + 2) * 3. In F#, you also use brackets to override precedence. Thus
// 'a -> string * 'a
let f x = someOtherFunction x, x
isn't the same as
// x:'a -> string
let f x = someOtherFunction (x, x)
(in this case, someOtherFunction is a function that returns a string.)
Notice that the brackets don't denote a function call; they're only there to control order of evaluation.
Sometimes, you want to define a function that doesn't take any input. You can't, however, define it like this:
let f = whatever
because that would make it a value that's immediately let-bound to whatever. Instead, you can let the function take a value of the built-in type unit. This type only has a single value, which is written ():
let f () = whatever
This means that f is a function that pattern matches its input against the only known value of unit.
Whenever you invoke f with (), the expression whatever is evaluated and returned.
Without the parentheses, the content executes once and never again. read_rest_of_csv has a type of bool: You are basically saying while true do ignore None.
The parentheses indicate that read_rest_of_csv has type unit -> bool, so every time you invoke it, it reads a row and moves the cursor. Otherwise, it will only do this once.
The answer to your question is that:
let read_rest_of_csv =
csv_data.Add(csv_fileH.ReadFields()) |> ignore
not csv_fileH.EndOfData
is not a function at all. This is no different from:
> let i = 1;;
val i : int = 1
This declares a binding with an integer value. If you want to declare a binding with a function value which takes no parameters, that looks like this:
> let i () = 1;;
val i : unit -> int
The exact same reasoning applies to read_rest_of_csv. Without the parenthesis, you are declaring a binding with type bool. With the parenthesis, you are declaring a binding with type unit->bool i.e. a binding with a function value where the function takes no inputs and returns a bool value.
Here is what I have so far:
type Maybe<'a> = option<'a>
let succeed x = Some(x)
let fail = None
let bind rest p =
match p with
| None -> fail
| Some r -> rest r
let rec whileLoop cond body =
if cond() then
match body() with
| Some() ->
whileLoop cond body
| None ->
fail
else
succeed()
let forLoop (xs : 'T seq) f =
using (xs.GetEnumerator()) (fun it ->
whileLoop
(fun () -> it.MoveNext())
(fun () -> it.Current |> f)
)
whileLoop works fine to support for loops, but I don't see how to get while loops supported. Part of the problem is that the translation of while loops uses delay, which I could not figure out in this case. The obvious implementation below is probably wrong, as it does not delay the computation, but runs it instead!
let delay f = f()
Not having delay also hinders try...with and try...finally.
There are actually two different ways of implementing continuation builders in F#. One is to represent delayed computations using the monadic type (if it supports some way of representing delayed computations, like Async<'T> or the unit -> option<'T> type as shown by kkm.
However, you can also use the flexibility of F# computation expressions and use a different type as a return value of Delay. Then you need to modify the Combine operation accordingly and also implement Run member, but it all works out quite nicely:
type OptionBuilder() =
member x.Bind(v, f) = Option.bind f v
member x.Return(v) = Some v
member x.Zero() = Some ()
member x.Combine(v, f:unit -> _) = Option.bind f v
member x.Delay(f : unit -> 'T) = f
member x.Run(f) = f()
member x.While(cond, f) =
if cond() then x.Bind(f(), fun _ -> x.While(cond, f))
else x.Zero()
let maybe = OptionBuilder()
The trick is that F# compiler uses Delay when you have a computation that needs to be delayed - that is: 1) to wrap the whole computation, 2) when you sequentially compose computations, e.g. using if inside the computation and 3) to delay bodies of while or for.
In the above definition, the Delay member returns unit -> M<'a> instead of M<'a>, but that's perfectly fine because Combine and While take unit -> M<'a> as their second argument. Moreover, by adding Run that evaluates the function, the result of maybe { .. } block (a delayed function) is evaluated, because the whole block is passed to Run:
// As usual, the type of 'res' is 'Option<int>'
let res = maybe {
// The whole body is passed to `Delay` and then to `Run`
let! a = Some 3
let b = ref 0
while !b < 10 do
let! n = Some () // This body will be delayed & passed to While
incr b
if a = 3 then printfn "got 3"
else printfn "got something else"
// Code following `if` is delayed and passed to Combine
return a }
This is a way to define computation builder for non-delayed types that is most likely more efficient than wrapping type inside a function (as in kkm's solution) and it does not require defining a special delayed version of the type.
Note that this problem does not happen in e.g. Haskell, because that is a lazy language, so it does not need to delay computations explicitly. I think that the F# translation is quite elegant as it allows dealing with both types that are delayed (using Delay that returns M<'a>) and types that represent just an immediate result (using Delay that returns a function & Run).
According to monadic identities, your delay should always be equivalent to
let delay f = bind (return ()) f
Since
val bind : M<'T> -> ('T -> M<'R>) -> M<'R>
val return : 'T -> M<'T>
the delay has the signature of
val delay : (unit -> M<'R>) -> M<'R>
'T being type-bound to unit. Note that your bind function has its arguments reversed from the customary order bind p rest. This is technically same but does complicate reading code.
Since you are defining the monadic type as type Maybe<'a> = option<'a>, there is no delaying a computation, as the type does not wrap any computation at all, only a value. So you definition of delay as let delay f = f() is theoretically correct. But it is not adequate for a while loop: the "body" of the loop will be computed before its "test condition," really before the bind is bound. To avoid this, you redefine your monad with an extra layer of delay: instead of wrapping a value, you wrap a computation that takes a unit and computes the value.
type Maybe<'a> = unit -> option<'a>
let return x = fun () -> Some(x)
let fail = fun() -> None
let bind p rest =
match p() with
| None -> fail
| Some r -> rest r
Note that the wrapped computation is not run until inside the bind function, i. e. not run until after the arguments to bind are bound themselves.
With the above expression, delay is correctly simplified to
let delay f = fun () -> f()