I am trying to wrap a call to sprintf function. Here's my attempt:
let p format args = "That was: " + (sprintf format args)
let a = "a"
let b = "b"
let z1 = p "A %s has invalid b" a
This seems to work, output is
val p : format:Printf.StringFormat<('a -> string)> -> args:'a -> string
val a : string = "a"
val b : string = "b"
val z1 : string = "That was: A a has invalid b"
But it wouldn't work with more than one arg:
let z2 = p "A %s has invalid b %A" a b
I get compile-time error:
let z2 = p "A %s has invalid b %A" a b;;
---------^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(7,10): error FS0003: This value is not a function and cannot be applied
How can I create a single function which would work with any number of args?
UPD. Tomas has suggested to use
let p format = Printf.kprintf (fun s -> "This was: " + s) format
It works indeed. Here's an example
let p format = Printf.kprintf (fun s -> "This was: " + s) format
let a = p "something like %d" 123
// val p : format:Printf.StringFormat<'a,string> -> 'a
// val a : string = "This was: something like 123"
But the thing is that main purpose of my function is to do some work except for formatring, so I tried to use the suggested code as follows
let q format =
let z = p format // p is defined as suggested
printf z // Some work with formatted string
let z = q "something like %d" 123
And it doesn't work again:
let z = q "something like %d" 123;;
----------^^^^^^^^^^^^^^^^^^^
stdin(30,15): error FS0001: The type ''c -> string' is not compatible with the type 'Printf.TextWriterFormat<('a -> 'b)>'
How could I fix it?
For this to work, you need to use currying - your function p needs to take the format and return a function returned by one of the printf functions (which can then be a function taking one or more arguments).
This cannot be done using sprintf (because then you would have to propagate the arguments explicitly. However, you can use kprintf which takes a continuation as the first argument::
let p format = Printf.kprintf (fun s -> "This was: " + s) format
The continuation is called with the formatted string and so you can do whatever you need with the resulting string before returning.
EDIT: To answer your extended question, the trick is to put all the additional work into the continuation:
let q format =
let cont z =
// Some work with formatted string
printf "%s" z
Printf.kprintf cont format
Related
How can I print argument function name that was used to call this function?
open System
open System.Threading.Tasks
let logger (f: ('a -> Task<'b>)) : ('a -> Task<'b>) =
printfn "Hey: %O" (nameof f) // I would like to print "myFunc", not "f"
f
let myFunc x = task {return x }
let d = (logger myFunc) 3
You could use the ReflectedDefinition(true) attribute, which automatically quotes the argument of a method call and gives you both the value (to use at runtime) and the code quotation from which you can (if the format is right) extract the name. This only seems to work with method calls though:
type Logger =
static member log([<ReflectedDefinition(true)>]f: Expr<('a -> Task<'b>)>) : ('a -> Task<'b>) =
match f with
| Patterns.WithValue(v, _, Patterns.Lambda(_, Patterns.Call(_, mi, _))) ->
printfn "Hello %s!" mi.Name
unbox v
| _ -> failwith "Wrong format"
let myFunc x = task {return x }
let d = (Logger.log myFunc) 3
The design and motivation of this is discussed in the F# 4.0 Speclet: Auto-Quotation of Arguments at Method Calls
In the F# core libraries there are functions whose signature seemingly changes based on the parameter at compile-time:
> sprintf "Hello %i" ;;
val it : (int -> string) = <fun:it#1>
> sprintf "Hello %s" ;;
val it : (string -> string) = <fun:it#2-1>
Is it possible to implement my own functions that have this property?
For example, could I design a function that matches strings with variable components:
matchPath "/products/:string/:string" (fun (category : string) (sku : string) -> ())
matchPath "/tickets/:int" (fun (id : int) -> ())
Ideally, I would like to do avoid dynamic casts.
There are two relevant F# features that make it possible to do something like this.
Printf format strings. The compiler handles format strings like "hi %s" in a special way. They are not limited just to printf and it's possible to use those in your library in a somewhat different way. This does not let you change the syntax, but if you were happy to specify your paths using e.g. "/products/%s/%d", then you could use this. The Giraffe library defines routef function, which uses this trick for request routing:
let webApp =
choose [
routef "/foo/%s/%s/%i" fooHandler
routef "/bar/%O" (fun guid -> text (guid.ToString()))
]
Type providers. Another option is to use F# type providers. With parameterized type providers, you can write a type that is parameterized by a literal string and has members with types that are generated by some F# code you write based on the literal string parameter. An example is the Regex type provider:
type TempRegex = Regex< #"^(?<Temperature>[\d\.]+)\s*°C$", noMethodPrefix = true >
TempRegex().Match("21.3°C").Temperature.TryValue
Here, the regular expression on the first line is static parameter of the Regex type provider. The type provider generates a Match method which returns an object with properties like Temperature that are based on the literal string. You would likely be able to use this and write something like:
MatchPath<"/products/:category/:sku">.Match(fun r ->
printfn "Got category %s and sku %s" r.Category r.Sku)
I tweaked your example so that r is an object with properties that have names matching to those in the string, but you could use a lambda with multiple parameters too. Although, if you wanted to specify types of those matches, you might need a fancier syntax like "/product/[category:int]/[sku:string]" - this is just a string you have to parse in the type provider, so it's completely up to you.
1st: Tomas's answer is the right answer.
But ... I had the same question.
And while I could understand it conceptually as "it has to be 'the string format thing' or 'the provider stuff'"
I could not tell my self that I got until I tried an implementation
... And it took me a bit .
I used FSharp.Core's printfs and Giraffe's FormatExpressions.fs as guidelines
And came up with this naive gist/implementation, inspired by Giraffe FormatExpressions.fs
BTW The trick is in this bit of magic fun (format: PrintfFormat<_, _, _, _, 'T>) (handle: 'T -> 'R)
open System.Text.RegularExpressions
// convert format pattern to Regex Pattern
let rec toRegexPattern =
function
| '%' :: c :: tail ->
match c with
| 'i' ->
let x, rest = toRegexPattern tail
"(\d+)" + x, rest
| 's' ->
let x, rest = toRegexPattern tail
"(\w+)" + x, rest
| x ->
failwithf "'%%%c' is Not Implemented\n" x
| c :: tail ->
let x, rest = toRegexPattern tail
let r = c.ToString() |> Regex.Escape
r + x, rest
| [] -> "", []
// Handler Factory
let inline Handler (format: PrintfFormat<_, _, _, _, 'T>) (handle: 'T -> string) (decode: string list -> 'T) =
format.Value.ToCharArray()
|> List.ofArray
|> toRegexPattern
|> fst, handle, decode
// Active Patterns
let (|RegexMatch|_|) pattern input =
let m = Regex.Match(input, pattern)
if m.Success then
let values =
[ for g in Regex(pattern).Match(input).Groups do
if g.Success && g.Name <> "0" then yield g.Value ]
Some values
else
None
let getPattern (pattern, _, _) = pattern
let gethandler (_, handle, _) = handle
let getDecoder (_, _, decode) = decode
let Router path =
let route1 =
Handler "/xyz/%s/%i"
(fun (category, id) ->
// process request
sprintf "handled: route1: %s/%i" category id)
(fun values ->
// convert matches
values |> List.item 0,
values
|> List.item 1
|> int32)
let route2 =
Handler "/xyz/%i"
(fun (id) -> sprintf "handled: route2: id: %i" id) // handle
(fun values -> values|> List.head |> int32) // decode
// Router
(match path with
| RegexMatch (getPattern route2) values ->
values
|> getDecoder route2
|> gethandler route2
| RegexMatch (getPattern route1) values ->
values
|> getDecoder route1
|> gethandler route1
| _ -> failwith "No Match")
|> printf "routed: %A\n"
let main argv =
try
let arg = argv |> Array.skip 1 |> Array.head
Router arg
0 // return an integer exit code
with
| Failure msg ->
eprintf "Error: %s\n" msg
-1
I would like to consolidate the following lines:
let result1 = add (numbers, ",")
let result2 = add (numbers, "\n")
into something like this:
let resultX = add (numbers, ",") |> add (numbers, "\n")
Can I compose functions like this?
NOTE:
I am learning F# and apologize if this question seems silly.
The code is below:
module Calculator
open FsUnit
open NUnit.Framework
open System
let add (numbers:string) =
let add (numbers:string) (delimiter:string) =
if (numbers.Contains(delimiter)) then
numbers.Split(delimiter.Chars(0)) |> Array.map Int32.Parse
|> Array.sum
else 0
let result1 = add numbers ","
let result2 = add numbers "\n"
if (result1 > 0 || result2 > 0) then
result1 + result2
else let _ , result = numbers |> Int32.TryParse
result
Tests:
[<Test>]
let ``adding empty string returns zero`` () =
let result = add ""
result |> should equal 0
[<Test>]
let ``adding one number returns number`` () =
let result = add "3"
result |> should equal 3
[<Test>]
let ``add two numbers`` () =
let result = add "3,4"
result |> should equal 7
[<Test>]
let ``add three numbers`` () =
let result = add "3,4,5"
result |> should equal 12
[<Test>]
let ``line feeds embedded`` () =
let result = add "3\n4"
result |> should equal 7
UPDATED
I receive the following error:
The type 'int' does not match the type 'string'
let add (numbers:string) =
let add (numbers:string) (delimiter:string) =
if (numbers.Contains(delimiter)) then
numbers.Split(delimiter.Chars(0)) |> Array.map Int32.Parse
|> Array.sum
else 0
let resultX = numbers |> add ","
|> add "\n"
Implemented Feedback:
let add (numbers:string) =
let add (numbers:string) (delimiters:char array) =
if numbers.Length = 0 then 0
else numbers.Split(delimiters) |> Array.map Int32.Parse
|> Array.sum
let delimiters = [|',';'\n'|]
add numbers delimiters
This is not an exact answer as I am not sure what you mean but it should give you some ideas.
let add01 (numbers:string) =
let delimiters : char array = [|',';'\n'|]
let inputArray : string array = numbers.Split(delimiters)
let numbers : string list = Array.toList(inputArray)
let rec add (numbers : string list) (total : int) : int =
match (numbers : string list) with
| ""::t ->
add t total
| h::t ->
let number = System.Int32.Parse h
let total = total + number
add t total
| [] -> total
add numbers 0
let numbers = "1,2,3\n4,5,6\n\n"
let result = add01 numbers
When given the following code the following error occurs, why?
// Type mismatch. Expecting a
// int -> 'a
// but given a
// string -> int
// The type 'int' does not match the type 'string'
let result = numbers |> add ","
|> add "\n"
Since this is an error stating that two types do not agree one needs to understand type inferencing and how to resolve such problems.
I will not explain type inferencing here as that is a large topic in itself, however I will give an example of a pattern that works successfully most of time for me in resolving such errors.
When F# compiles code it uses type inferencing to add the missing types to functions and values before doing a type check and it is the type check that is failing. So to see what the compiler sees for the types we will manually add them here and factor out the parts of the code that are not causing a problem leaving us with the cause of the error hopefully in something then becomes obvious to fix.
The only things that have types are:
result
=
numbers
|>
add
","
"\n"
The types for the values are easy:
result : int
numbers : string
"," : string
"\n" : string
I don't recall F# treating equals (=) as a function but here is how to think of it.
= : 'a -> 'a
The pipeline operator
let (|>) (x : 'a) f = f (x : 'a)
For resolving the problem just think of the pipeline operator as syntactic sugar.
See examples below for better understanding.
The add function
add : string -> string -> int
So lets refine the error down to its essence.
//Type mismatch. Expecting a
// int -> 'a
//but given a
// string -> int
//The type 'int' does not match the type 'string'
let result = numbers |> add ","
|> add "\n"
Add the type signatures to the values and verify we get the same error.
This is what type inferencing would do and we did it manually.
//Type mismatch. Expecting a
// int -> int
//but given a
// string -> int
//The type 'int' does not match the type 'string'
let (result : int) = (numbers : string) |> add ("," : string)
|> add ("\n" : string)
Now think of the code as a mathematical expression which can be factored.
Factor out the first pipeline operator and verify we get the same error.
Notice the error is now only part of r2
//Expecting a
// int -> 'a
//but given a
// string -> int
//The type 'int' does not match the type 'string'
let (result : int) =
let r1 = (numbers : string) |> add ("," : string)
let r2 = r1 |> add ("\n" : string)
r2
Undo the syntactic sugar for the second pipeline operator and verify we get the same error.
Notice the error is now only part of r2; specifically the r1 argument
//This expression was expected to have type
// string
//but here has type
// int
let (result : int) =
let r1 = (numbers : string) |> add ("," : string)
let r2 = add ("\n" : string) r1
r2
Add the type to r1 and verify we get the same error.
//This expression was expected to have type
// string
//but here has type
// int
let (result : int) =
let (r1 : int) = (numbers : string) |> add ("," : string)
let r2 = add ("\n" : string) r1
r2
At this point the error should be obvious.
The result of the first pipeline operator is an int and is passed to the add function as the second argument.
The add function expects a string for the second argument but was given an int.
To better understand how the pipeline operator works I created an equivalent user defined operator for this demonstration.
These are some helper functions for the demonstration.
let output1 w =
printfn "1: %A" w
let output2 w x =
printfn "1: %A 2: %A" w x
let output3 w x y =
printfn "1: %A 2: %A 3: %A" w x y
let output4 w x y z =
printfn "1: %A 2: %A 3: %A 4: %A" w x y z
Using the output functions without the pipeline operator.
output1 "a"
1: "a"
output2 "a" "b"
1: "a" 2: "b"
output3 "a" "b" "c"
1: "a" 2: "b" 3: "c"
output4 "a" "b" "c" "d"
1: "a" 2: "b" 3: "c" 4: "d"
Notice that the output is in the same order as the input.
Using the output functions with the pipeline operator.
// let (|>) x f = fx
"a" |> output1
1: "a"
"a" |> output2 "b"
1: "b" 2: "a"
"a" |> output3 "b" "c"
1: "b" 2: "c" 3: "a"
"a" |> output4 "b" "c" "d"
1: "b" 2: "c" 3: "d" 4: "a"
NOTICE that the last argument for the output functions is the value on the left of the pipeline operator ("a") because of the use of the pipeline operator (|>).
// See section 3.7 of the F# specification on how to define user defined operators.
Using the output functions with the user defined pipeline operator.
let (#.) x f = f x
"a" #. output1
1: "a"
"a" #. output2 "b"
1: "b" 2: "a"
"a" #. output3 "b" "c"
1: "b" 2: "c" 3: "a"
"a" #. output4 "b" "c" "d"
1: "b" 2: "c" 3: "d" 4: "a"
I'm not aware of any universal way to compose functions like you seem to be asking, but if you only need to vary one argument, one option is to create a list of arguments, and then map over those:
let results = [","; "\n"] |> List.map (add numbers)
If you do this, then results is an int list, and then you need to decide what to do with that list. In this case, it would seem appropriate to sum over the list, but given the current conditionals that check if result1 or result2 are positive, that doesn't seem appropriate.
All that said, given the current test cases supplied, there's no reason to make it more complicated than it has to be. This implementation also passes all the tests:
let add =
let split (x : string) =
x.Split([| ','; '\n' |], StringSplitOptions.RemoveEmptyEntries)
split >> Array.map Int32.Parse >> Array.sum
This isn't a particularly robust implementation, as it'll fail if the string contains characters that can't be parsed into integers, but so will the OP implementation.
I have written a function that takes an array as input and returns an array of equal size as output. For example:
myFunc [| "apple"; "orange"; "banana" |]
> val it : (string * string) [] =
[|("red", "sphere"); ("orange", "sphere"); ("yellow", "oblong")|]
Now I want to assign the results via a let binding. For example:
let [|
( appleColor, appleShape );
( orangeColor, orangeShape );
( bananaColor, bananaShape )
|] =
myFunc [| "apple"; "orange"; "banana" |]
Which works great...
> val orangeShape : string = "sphere"
> val orangeColor : string = "orange"
> val bananaShape : string = "oblong"
> val bananaColor : string = "yellow"
> val appleShape : string = "sphere"
> val appleColor : string = "red"
...except it produces a warning:
warning FS0025: Incomplete pattern matches on this expression. For example, the value '[|_; _; _; _|]' may indicate a case not covered by the pattern(s).
The source and reason for the warning has already been covered, I'm just looking for a succinct work-around. This function call occurs near the top of my function, and I don't like the idea of putting the entire function body inside a match:
let otherFunc =
match myFunc [| "apple"; "orange"; "banana" |] with
| [|
( appleColor, appleShape );
( orangeColor, orangeShape );
( bananaColor, bananaShape )
|] ->
// ... the rest of my function logic
| _ -> failwith "Something impossible just happened!"
That just smells bad. I don't like the idea of ignoring the warning either - goes against my better judgment. Are there any other options open to me, or do I just need to find a different approach entirely?
One possibility if you expect this kind of calling pattern to be frequent is to make wrappers that act on the sizes of tuples you expect, e.g.
myFunc3 (in1,in2,in3) =
match myFunc [|in1;in2;in3|] with
[|out1;out2;out3|] -> out1, out2, out3
_ -> failwith "Internal error"
etc. But all it does is move the ugly code to a standard place, and writing out the wrappers will be inconvenient.
I don't think there's any better option with this API, because there's no way to tell the compiler that myFunc always returns the same number of elements it is passed.
Another option might be to replace myFunc with an IDisposable class:
type MyClass() =
let expensiveResource = ...
member this.MyFunc(v) = ...calculate something with v using expensiveResource
interface IDisposable with
override this.Dispose() = // cleanup resource
and then use it in a block like
use myClass = new MyClass()
let appleColor, appleShape = myClass.MyFunc(apple)
...
Adapting #Ganesh's answer, here's a primitive way to approach the problem:
let Tuple2Map f (u, v)
= (f u, f v)
let Tuple3Map f (u, v, w)
= (f u, f v, f w)
let Tuple4Map f (u, v, w, x)
= (f u, f v, f w, f x)
Example:
let Square x = x * x
let (a,b) = Tuple2Map Square (4,6)
// Output:
// val b : int = 36
// val a : int = 16
But I guess something even more primitive would be this:
let Square x = x * x
let (a,b) = (Square 4, Square 6)
And if the function name is too long, e.g.
// Really wordy way to assign to (a,b)
let FunctionWithLotsOfInput w x y z = w * x * y * z
let (a,b) =
(FunctionWithLotsOfInput input1 input2 input3 input4A,
FunctionWithLotsOfInput input1 input2 input3 input4B)
We can define temporary function
let FunctionWithLotsOfInput w x y z = w * x * y * z
// Partially applied function, temporary function
let (a,b) =
let f = (FunctionWithLotsOfInput input1 input2 input3)
(f input4A, f input4B)
I'd like to create a builder that builds expressions that returns something like a continuation after each step.
Something like this:
module TwoSteps =
let x = stepwise {
let! y = "foo"
printfn "got: %A" y
let! z = y + "bar"
printfn "got: %A" z
return z
}
printfn "two steps"
let a = x()
printfn "something inbetween"
let b = a()
Where the 'let a' line returns something containing the rest of the expressions to be evaluated later on.
Doing this with a separate type for each number of steps is straightforward but of course not particularly useful:
type Stepwise() =
let bnd (v: 'a) rest = fun () -> rest v
let rtn v = fun () -> Some v
member x.Bind(v, rest) =
bnd v rest
member x.Return v = rtn v
let stepwise = Stepwise()
module TwoSteps =
let x = stepwise {
let! y = "foo"
printfn "got: %A" y
let! z = y + "bar"
printfn "got: %A" z
return z
}
printfn "two steps"
let a = x()
printfn "something inbetween"
let b = a()
module ThreeSteps =
let x = stepwise {
let! y = "foo"
printfn "got: %A" y
let! z = y + "bar"
printfn "got: %A" z
let! z' = z + "third"
printfn "got: %A" z'
return z
}
printfn "three steps"
let a = x()
printfn "something inbetween"
let b = a()
printfn "something inbetween"
let c = b()
And the results are what I'm looking for:
two steps
got: "foo"
something inbetween
got: "foobar"
three steps
got: "foo"
something inbetween
got: "foobar"
something inbetween
got: "foobarthird"
But I can't figure out what the general case of this would be.
What I'd like is to be able to feed events into this workflow, so you could write something like:
let someHandler = Stepwise<someMergedEventStream>() {
let! touchLocation = swallowEverythingUntilYouGetATouch()
startSomeSound()
let! nextTouchLocation = swallowEverythingUntilYouGetATouch()
stopSomeSound()
}
And have events trigger a move to the next step in the workflow. (In particular, I want to play with this sort of thing in MonoTouch - F# on the iPhone. Passing around objc selectors drives me insane.)
the problem with your implementation is that it returns "unit -> 'a" for each call to Bind, so you'll get a different type of result for different number of steps (in general, this is a suspicious definition of monad/computation expression).
A correct solution should be to use some other type, which can represent a computation with arbitrary number of steps. You'll also need to distinguish between two types of steps - some steps just evaluate next step of the computation and some steps return a result (via the return keyword). I'll use a type seq<option<'a>>. This is a lazy sequence, so reading the next element will evaluate the next step of the computation. The sequence will contain None values with the exception of the last value, which will be Some(value), representing the result returned using return.
Another suspicious thing in your implementation is a non-standard type of Bind member. The fact that your bind takes a value as the first parameter means that your code looks a bit simpler (you can write let! a = 1) however, you cannot compose stepwise computation. You may want to be able to write:
let foo() = stepwise {
return 1; }
let bar() = stepwise {
let! a = foo()
return a + 10 }
The type I described above will allow you to write this as well. Once you have the type, you just need to follow the type signature of Bind and Return in the implementation and you'll get this:
type Stepwise() =
member x.Bind(v:seq<option<_>>, rest:(_ -> seq<option<_>>)) = seq {
let en = v.GetEnumerator()
let nextVal() =
if en.MoveNext() then en.Current
else failwith "Unexpected end!"
let last = ref (nextVal())
while Option.isNone !last do
// yield None for each step of the source 'stepwise' computation
yield None
last := next()
// yield one more None for this step
yield None
// run the rest of the computation
yield! rest (Option.get !last) }
member x.Return v = seq {
// single-step computation that yields the result
yield Some(v) }
let stepwise = Stepwise()
// simple function for creating single-step computations
let one v = stepwise.Return(v)
Now, let's look at using the type:
let oneStep = stepwise {
// NOTE: we need to explicitly create single-step
// computations when we call the let! binder
let! y = one( "foo" )
printfn "got: %A" y
return y + "bar" }
let threeSteps = stepwise {
let! x = oneStep // compose computations :-)
printfn "got: %A" x
let! y = one( x + "third" )
printfn "got: %A" y
return "returning " + y }
If you want to run the computation step-by-step, you can simply iterate over the returned sequence, for example using the F# for keyword. The following also prints the index of the step:
for step, idx in Seq.zip threeSteps [ 1 .. 10] do
printf "STEP %d: " idx
match step with
| None _ -> ()
| Some(v) -> printfn "Final result: %s" v
Hope this helps!
PS: I found this problem very interesting! Would you mind if I addapted my answer into a blog post for my blog (http://tomasp.net/blog)? Thanks!
Monads and computation builders confuse the hell out of me, but I've adapted something I've made in an earlier SO post. Maybe some bits and pieces can be of use.
The code below contains an action queue, and a form where the Click event listens to the next action available in the action queue. The code below is an example with 4 actions in succession. Execute it in FSI and start clicking the form.
open System.Collections.Generic
open System.Windows.Forms
type ActionQueue(actions: (System.EventArgs -> unit) list) =
let actions = new Queue<System.EventArgs -> unit>(actions) //'a contains event properties
with
member hq.Add(action: System.EventArgs -> unit) =
actions.Enqueue(action)
member hq.NextAction =
if actions.Count=0
then fun _ -> ()
else actions.Dequeue()
//test code
let frm = new System.Windows.Forms.Form()
let myActions = [
fun (e:System.EventArgs) -> printfn "You clicked with %A" (e :?> MouseEventArgs).Button
fun _ -> printfn "Stop clicking me!!"
fun _ -> printfn "I mean it!"
fun _ -> printfn "I'll stop talking to you now."
]
let aq = new ActionQueue(myActions)
frm.Click.Add(fun e -> aq.NextAction e)
//frm.Click now executes the 4 actions in myActions in order and then does nothing on further clicks
frm.Show()
You can click the form 4 times and then nothing happens with further clicks.
Now execute the following code, and the form will respond two more times:
let moreActions = [
fun _ -> printfn "Ok, I'll talk to you again. Just don't click anymore, ever!"
fun _ -> printfn "That's it. I'm done with you."
]
moreActions |> List.iter (aq.Add)