I have byte array as input. I would like to convert that array to string that contains hexadecimal representation of array values. This is F# code:
let ByteToHex bytes =
bytes
|> Array.map (fun (x : byte) -> String.Format("{0:X2}", x))
let ConcatArray stringArray = String.Join(null, (ByteToHex stringArray))
This produces result I need, but I would like to make it more compact so that I have only one function.
I could not find function that would concat string representation of each byte at the end
of ByteToHex.
I tried Array.concat, concat_map, I tried with lists, but the best I could get is array or list of strings.
Questions:
What would be simplest, most elegant way to do this?
Is there string formatting construct in F# so that I can replace String.Format from System assembly?
Example input: [|0x24uy; 0xA1uy; 0x00uy; 0x1Cuy|] should produce string "24A1001C"
There is nothing inherently wrong with your example. If you'd like to get it down to a single expression then use the String.contcat method.
let ByteToHex bytes =
bytes
|> Array.map (fun (x : byte) -> System.String.Format("{0:X2}", x))
|> String.concat System.String.Empty
Under the hood, String.concat will just call into String.Join. Your code may have to be altered slighly though because based on your sample you import System. This may create a name resolution conflict between F# String and System.String.
If you want to transform and accumulate in one step, fold is your answer. sprintf is the F# string format function.
let ByteToHex (bytes:byte[]) =
bytes |> Array.fold (fun state x-> state + sprintf "%02X" x) ""
This can also be done with a StringBuilder
open System.Text
let ByteToHex (bytes:byte[]) =
(StringBuilder(), bytes)
||> Array.fold (fun state -> sprintf "%02X" >> state.Append)
|> string
produces:
[|0x24uy; 0xA1uy; 0x00uy; 0x1Cuy|] |> ByteToHex;;
val it : string = "24A1001C"
Here's another answer:
let hashFormat (h : byte[]) =
let sb = StringBuilder(h.Length * 2)
let rec hashFormat' = function
| _ as currIndex when currIndex = h.Length -> sb.ToString()
| _ as currIndex ->
sb.AppendFormat("{0:X2}", h.[currIndex]) |> ignore
hashFormat' (currIndex + 1)
hashFormat' 0
The upside of this one is that it's tail-recursive and that it pre-allocates the exact amount of space in the string builder as will be required to convert the byte array to a hex-string.
For context, I have it in this module:
module EncodingUtils
open System
open System.Text
open System.Security.Cryptography
open Newtonsoft.Json
let private hmacmd5 = new HMACMD5()
let private encoding = System.Text.Encoding.UTF8
let private enc (str : string) = encoding.GetBytes str
let private json o = JsonConvert.SerializeObject o
let md5 a = a |> (json >> enc >> hmacmd5.ComputeHash >> hashFormat)
Meaning I can pass md5 any object and get back a JSON hash of it.
Here's another. I'm learning F#, so feel free to correct me with more idiomatic ways of doing this:
let bytesToHexString (bytes : byte[]) : string =
bytes
|> Seq.map (fun c -> c.ToString("X2"))
|> Seq.reduce (+)
Looks fine to me. Just to point out another, in my opinion, very helpful function in the Printf module, have a look at ksprintf. It passes the result of a formated string into a function of your choice (in this case, the identity function).
val ksprintf : (string -> 'd) -> StringFormat<'a,'d> -> 'a
sprintf, but call the given 'final' function to generate the result.
To be honest, that doesn't look terrible (although I also have very little F# experience). Does F# offer an easy way to iterate (foreach)? If this was C#, I might use something like (where raw is a byte[] argument):
StringBuilder sb = new StringBuilder();
foreach (byte b in raw) {
sb.Append(b.ToString("x2"));
}
return sb.ToString()
I wonder how that translates to F#...
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 have a type that I'm trying to understand by writing unit tests against it, however I can't reason what to do with PrintfFormat
type ValueFormat<'p,'st,'rd,'rl,'t,'a> = {
format: PrintfFormat<'p,'st,'rd,'rl,'t>
paramNames: (string list) option
handler: 't -> 'a
}
with
static member inline construct (this: ValueFormat<_,_,_,_,_,_>) =
let parser s =
s |> tryKsscanf this.format this.handler
|> function Ok x -> Some x | _ -> None
let defaultNames =
this.format.GetFormatterNames()
|> List.map (String.replace ' ' '_' >> String.toUpperInvariant)
|> List.map (sprintf "%s_VALUE")
let names = (this.paramNames ?| defaultNames) |> List.map (sprintf "<%s>")
let formatTokens = this.format.PrettyTokenize names
(parser, formatTokens)
I feel confident that I can figure everything out but PrintfFormat is throwing me with all those generics.
The file I'm looking at for the code I want to unit test is here for the FSharp.Commandline framework.
My question is, what is PrintfFormat and how should it be used?
A link to the printf.fs file is here. It contains the definition of PrintfFormat
The PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple> type, as defined in the F# source code, has four type parameters:
'Result is the type that your formatting/parsing function produces. This is string for sprintf
'Printer is a type of a function generated based on the format string, e.g. "%d and %s" will give you a function type int -> string -> 'Result
'Tuple is a tuple type generated based on the format string, e.g. "%d and %s" will give you a tuple type int * string.
'State and 'Residue are type parameters that are used when you have a custom formatter using %a, but I'll ignore that for now for simplicity (it's never needed unless you have %a format string)
There are two ways of using the type. Either for formatting, in which case you'll want to write a function that returns 'Printer as the result. The hard thing about this is that you need to construct the return function using reflection. Here is an example that works only with one format string:
open Microsoft.FSharp.Reflection
let myformat (fmt:PrintfFormat<'Printer,obj,obj,string,'Tuple>) : 'Printer =
unbox <| FSharpValue.MakeFunction(typeof<'Printer>, fun o ->
box (o.ToString()) )
myformat "%d" 1
myformat "%s" "Yo"
This simply returns the parameter passed as a value for %d or %s. To make this work for multiple arguments, you'd need to construct the function recursively (so that it's not just e.g. int -> string but also int -> (int -> string))
In the other use, you define a function that returns 'Tuple and it needs to create a tuple containing values according to the specified formatting string. Here is a small sample that only handles %s and %d format strings:
open FSharp.Reflection
let myscan (fmt:PrintfFormat<'Printer,obj,obj,string,'Tuple>) : 'Tuple =
let args =
fmt.Value
|> Seq.pairwise
|> Seq.choose (function
| '%', 'd' -> Some(box 123)
| '%', 's' -> Some(box "yo")
| _ -> None)
unbox <| FSharpValue.MakeTuple(Seq.toArray args, typeof<'Tuple>)
myscan "%d %s %d"
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 have a text file that contains the following and I need to retrieve the value assigned to taskId, which in this case is AWc34YBAp0N7ZCmVka2u.
projectKey=ProjectName
serverUrl=http://localhost:9090
serverVersion=10.5.32.3
strong text**interfaceUrl=http://localhost:9090/interface?id=ProjectName
taskId=AWc34YBAp0N7ZCmVka2u
taskUrl=http://localhost:9090/api/ce/task?id=AWc34YBAp0N7ZCmVka2u
I have two different ways of reading the file that I've wrote.
let readLines (filePath:string) = seq {
use sr = new StreamReader (filePath)
while not sr.EndOfStream do
yield sr.ReadLine ()
}
readLines (FindFile currentDirectory "../**/sample.txt")
|> Seq.iter (fun line ->
printfn "%s" line
)
and
let readLines (filePath:string) =
(File.ReadAllLines filePath)
readLines (FindFile currentDirectory "../**/sample.txt")
|> Seq.iter (fun line ->
printfn "%s" line
)
At this point, I don't know how to approach getting the value I need. Options that, I think, are on the table are:
use Contains()
Regex
Record type
Active Pattern
How can I get this value returned and fail if it doesn't exist?
I think all the options would be reasonable - it depends on how complex the file will actually be. If there is no escaping then you can probably just look for = in the line and use that to split the line into a key value pair. If the syntax is more complex, this might not always work though.
My preferred method would be to use Split on string - you can then filter to find values with your required key, map to get the value and use Seq.head to get the value:
["foo=bar"]
|> Seq.map (fun line -> line.Split('='))
|> Seq.filter (fun kvp -> kvp.[0] = "foo")
|> Seq.map (fun kvp -> kvp.[1])
|> Seq.head
Using active patterns, you could define a pattern that takes a string and splits it using = into a list:
let (|Split|) (s:string) = s.Split('=') |> List.ofSeq
This then lets you get the value using Seq.pick with a pattern matching that looks for strings where the substring before = is e.g. foo:
["foo=bar"] |> Seq.pick (function
| Split ["foo"; value] -> Some value
| _ -> None)
The active pattern trick is quite neat, but it might be unnecessarily complicating the code if you only need this in one place.
I'm writing a quick DB perf test, and chose F# so I can get more practice.
I've created a method, measureSelectTimes, which has the signature Guid list * Guid list -> IDbCommand -> TimeSpan * TimeSpan.
Then, I call it:
let runTests () =
let sqlCeConn : IDbConnection = initSqlCe() :> IDbConnection
let sqlServerConn : IDbConnection = initSqlServer() :> IDbConnection
let dbsToTest = [ sqlCeConn; sqlServerConn ]
let cmds : seq<IDbCommand> = dbsToTest |> Seq.map initSchema
let ids : seq<Guid list * Guid list> = cmds |> Seq.map loadData
let input = Seq.zip ids cmds
let results = input |> Seq.map (fun i -> measureSelectTimes (fst i) (snd i))
// ...
I've annotated explicitly with types to clarify.
What I can't figure out is how to call measureSelectTimes without the lambda. I'd like to partially apply the ids to it like this: ids |> Seq.map measureSelectTimes but then I don't know what to do with the resulting partially applied functions to then map onto the cmds. What's the syntax for this?
You can use Seq.map2:
Seq.map2 measureSelectTimes ids cmds
Or
(ids, cmds) ||> Seq.map2 measureSelectTimes
Your measureSelectTimes function takes two arguments as separate arguments, but you instead need a function that takes them as a tuple. One option is to just change the function to take a tuple (if it is logical for the arguments to be tupled).
Alternative, you can write a cobinator that turns a function taking two arguments into a function taking tuple. This is usually called uncurry and it exists in some functional language:
let uncurry f (a, b) = f a b
Then you can write:
input |> Seq.map (uncurry measureSelectTimes)
This looks okay for a simple use like this, but I think that using combinators too much in F# is not a good idea as it makes code difficult to read for less experienced functional programmers. I would probably write something like this (because I find that more readable):
[ for (time1, time2) in input -> measureSelectTimes time1 time2 ]
One approach is to change the signature of measureSelectTimes to
(Guid list * Guid list) * IDbCommand -> TimeSpan * TimeSpan
Then you can change the map call to
let results = input |> Seq.map measureSelectTimes
// or
let results = Seq.map measureSelectTimes input