I have an array of numbers in string format (e.g. [|"1"; "2"; "3" ...|]) and want to convert them to doubles, however I want to do it in CultureInvariant way. Of course I could do:
[|"1"; "2"|] |> Array.map (fun (a) -> Double.Parse(a, CultureInfo.InvariantCulture))
However, is there any way to do it like this:
[|"1"; "2"|] |> Array.map Double.Parse
, but with CultureInfo.InvariantCulture? This code will look much more readable. In another words, are there any ways to pass CultureInfo.InvariantCulture to Double.parse in flow, or set CultureInfo.InvariantCulture globally for all program/script.
In F# double and float are the same thing, and they both correspond to a C# double. See this answer.
Therefore you can simply use the float operator for this, which handles conversions from many types including strings:
[|"1"; "2"|] |> Array.map float
The F# conversion operators all sensibly use CultureInfo.InvariantCulture without the need for you to specify it: See this function from the F# source code used by the float operator.
If you want to use C# compatible terminology you can use the double operator, which is just an alias for float.
If you need a 32-bit float (the C# float), you can use float32.
Pretty straightforward to define a helper function and use that:
let ParseInvariant a = Double.Parse(a, CultureInfo.InvariantCulture)
let b = [|"1"; "2"|] |> Array.map ParseInvariant
or define an extension method:
type Double with
static member ParseInvariant a = Double.Parse(a, CultureInfo.InvariantCulture)
let b = [|"1"; "2"|] |> Array.map Double.ParseInvariant
Related
In F# one comes across this sort of thing:
let p = Earth().GetCountry1().GetPopulation()
Sometimes I find myself wanting to separate the argument from the function as is usually done in F#:
let p = ((Earth ()).GetCountry1 ()).GetPopulation ()
which requires many parentheses. Is there a function, or can someone think of one, which can be used in place of the dot operator, which facilitates a more elegant way of maintaining the space between function and argument -- something like this?
let dot method arg obj = obj.method arg
let p = Earth () |> dot GetCountry1 () |> dot GetPopulation ()
(My dot causes a compiler error.)
The original code is perfectly idiomatic F#. There's no need to change it.
However, sometimes you have an F# function pipeline and you need to call a method in the middle of it. The neatest way to do this is with a lambda:
aValue
|> aFunction parameter
|> anotherFunction
|> fun x -> x.Method()
|> oneLastFunction
The function you're trying to write is not possible in a statically typed language. This would need to be added as a language feature, or you can simply use a lambda as shown above.
First off, F# is a multi-paradigm language, so writing code in an OOP style is perfectly valid. If you are consuming C# libraries, this is very common.
I would suggest using the OOP-style (no space before arguments) for the OOP-style code and the functional-style (space after arguments) for the functional-style code.
There is no built-in mechanism for piping members in F#. This could be enabled in the future with the short-hand accessor suggestion or the lenses suggestion.
For now, the quickest solution for the functional-style is to write an anonymous function:
let p =
Earth ()
|> fun x -> x.getCountry1 ()
|> fun x -> x.getPopulation ()
If you do this frequently, it might be best to write a collection of helper functions:
let country1 x =
x.getCountry1 ()
let population x =
x.getPopulation ()
let p =
Earth ()
|> country1
|> population
You could probably implement your dot function using reflection but that would have a run-time overhead, which is probably not worth it.
I am running into difficulty with F# in numerous scenarios. I believe I'm not grasping some fundamental concepts. I'm hoping someone can track my reasoning and figure out the (probably many) things I'm missing.
Say I'm using Xunit. What I'd like to do is, provided two lists, apply the Assert.Equal method pairwise. For instance:
Open Xunit
let test1 = [1;2;3]
let test2 = [1;2;4]
List.map2 Assert.Equal test1 test2
The compiler complains that the function Equal does not take one parameter. As far as I can tell, shouldn't map2 be providing it 2 parameters?
As a sanity check, I use the following code in f# immediate:
let doequal = fun x y -> printf "result: %b\n" (x = y)
let test1 = [1;2;3]
let test2 = [1;2;4]
List.map2 doequal test1 test2;;
This seems identical. doequal is a lambda taking two generic parameters and returning unit. List.map2 hands each argument pairwise into the lambda and I get exactly what I expected as output:
result: true
result: true
result: false
So what gives? Source shows Xunit.Equal has signature public static void Equal<T>(T expected, T actual). Why won't my parameters map right over the method signature?
EDIT ONE
I thought two variables x and y vs a tuple (x, y) could construct and deconstruct interchangeably. So I tried two options and got different results. It seems the second may be further along than the first.
List.map2 Assert.Equal(test1, test2)
The compiler now complains that 'Successive arguments should be separated spaces or tupled'
List.map2(Assert.Equal(test1, test2))
The compiler now complains that 'A unique overload method could not be determined... A type annotation may be needed'
I think that part of the problem comes from mixing methods (OO style) and functions (FP style).
FP style functions have multiple parameters separated by spaces.
OO style methods have parens and parameters separated by commas.
Methods in other .NET libraries are always called using "tuple" syntax (actually subtly different from tuples though) and a tuple is considered to be one parameter.
The F# compiler tries to handle both approaches, but needs some help occasionally.
One approach is to "wrap" the OO method with an FP function.
// wrap method call with function
let assertEqual x y = Assert.Equal(x,y)
// all FP-style functions
List.map2 assertEqual test1 test2
If you don't create a helper function, you will often need to convert multiple function parameters to one tuple when calling a method "inline" with a lambda:
List.map2 (fun x y -> Assert.Equal(x,y)) test1 test2
When you mix methods and functions in one line, you often get the "Successive arguments should be separated" error.
printfn "%s" "hello".ToUpper()
// Error: Successive arguments should be separated
// by spaces or tupled
That's telling you that the compiler is having problems and needs some help!
You can solve this with extra parens around the method call:
printfn "%s" ("hello".ToUpper()) // ok
Or sometimes, with a reverse pipe:
printfn "%s" <| "hello".ToUpper() // ok
The wrapping approach is often worth doing anyway so that you can swap the parameters to make it more suitable for partial application:
// wrap method call with function AND swap params
let contains searchFor (s:string) = s.Contains(searchFor)
// all FP-style functions
["a"; "b"; "c"]
|> List.filter (contains "a")
Note that in the last line I had to use parens to give precedence to contains "a" over List.filter
public static void Equal<T>(T expected, T actual)
doesn't take two parameters - it takes one parameter, which is a tuple with two elements: (T expected, T actual).
Try this instead:
List.map2 Assert.Equal(test1, test2)
It's all there in the type signatures.
The signature for Assert.Equals is something along the lines of 'a * 'a -> unit. List.map2 expects a 'a -> 'b -> 'c.
They just don't fit together.
List.map2 (fun x y -> Assert.Equal(x,y)) test1 test2 - works because the lambda wrapping Equals has the expected signature.
List.zip test1 test2 |> List.map Assert.Equal - works because you now have a single list of tuples, and since List.map wants an 'a -> 'b function (where 'a is now a tuple), Assert.Equal is now fair game.
It's simply not true that two values and a tuple are implicitly interchangeable. At least not as far as F# the language is concerned, or the underlying IL representation is concerned. You can think that it's that way when you call into F# code from, say, C# - an 'a -> 'b -> 'c function there is indeed called the same way syntactically as an 'a * 'b -> 'c function - but this is more of an exception than a rule.
According to its signature Xunit.Assert.Equal() takes a single 2 values tuple parameter
For starters, I'm a novice in functional programming and F#, therefore I don't know if it's possible to do such thing at all. So let's say we have this function:
let sum x y z = x + y + z
And for some reason, we want to invoke it using the elements from a list as an arguments. My first attempt was just to do it like this:
//Seq.fold (fun f arg -> f arg) sum [1;2;3]
let rec apply f args =
match args with
| h::hs -> apply (f h) hs
| [] -> f
...which doesn't compile. It seems impossible to determine type of the f with a static type system. There's identical question for Haskell and the only solution uses Data.Dynamic to outfox the type system. I think the closest analog to it in F# is Dynamitey, but I'm not sure if it fits. This code
let dynsum = Dynamitey.Dynamic.Curry(sum, System.Nullable<int>(3))
produces dynsum variable of type obj, and objects of this type cannot be invoked, furthermore sum is not a .NET Delegate.So the question is, how can this be done with/without that library in F#?
F# is a statically typed functional language and so the programming patterns that you use with F# are quite different than those that you'd use in LISP (and actually, they are also different from those you'd use in Haskell). So, working with functions in the way you suggested is not something that you'd do in normal F# programming.
If you had some scenario in mind for this function, then perhaps try asking about the original problem and someone will help you find an idiomatic F# approach!
That said, even though this is not recommended, you can implement the apply function using the powerful .NET reflection capabilities. This is slow and unsafe, but if is occasionally useful.
open Microsoft.FSharp.Reflection
let rec apply (f:obj) (args:obj list) =
let invokeFunc =
f.GetType().GetMethods()
|> Seq.find (fun m ->
m.Name = "Invoke" &&
m.GetParameters().Length = args.Length)
invokeFunc.Invoke(f, Array.ofSeq args)
The code looks at the runtime type of the function, finds Invoke method and calls it.
let sum x y z = x + y + z
let res = apply sum [1;2;3]
let resNum = int res
At the end, you need to convert the result to an int because this is not statically known.
I have a list of words and a list of associated part of speech tags. I want to iterate over both, simultaneously (matched index) using each indexed tuple as input to a .NET function. Is this the best way (it works, but doesn't feel natural to me):
let taggingModel = SeqLabeler.loadModel(lthPath +
"models\penn_00_18_split_dict.model");
let lemmatizer = new Lemmatizer(lthPath + "v_n_a.txt")
let input = "the rain in spain falls on the plain"
let words = Preprocessor.tokenizeSentence( input )
let tags = SeqLabeler.tagSentence( taggingModel, words )
let lemmas = Array.map2 (fun x y -> lemmatizer.lookup(x,y)) words tags
Your code looks quite good to me - most of it deals with some loading and initialization, so there isn't much you could do to simplify that part. Alternatively to Array.map2, you could use Seq.zip combined with Seq.map - the zip function combines two sequences into a single one that contains pairs of elements with matching indices:
let lemmas = Seq.zip words tags
|> Seq.map (fun (x, y) -> lemmatizer.lookup (x, y))
Since lookup function takes a tuple that you got as an argument, you could write:
// standard syntax using the pipelining operator
let lemmas = Seq.zip words tags |> Seq.map lemmatizer.lookup
// .. an alternative syntax doing exactly the same thing
let lemmas = (words, tags) ||> Seq.zip |> Seq.map lemmatizer.lookup
The ||> operator used in the second version takes a tuple containing two values and passes them to the function on the right side as two arguments, meaning that (a, b) ||> f means f a b. The |> operator takes only a single value on the left, so (a, b) |> f would mean f (a, b) (which would work if the function f expected tuple instead of two, space separated, parameters).
If you need lemmas to be an array at the end, you'll need to add Array.ofSeq to the end of the processing pipeline (all Seq functions work with sequences, which correspond to IEnumerable<T>)
One more alternative is to use sequence expressions (you can use [| .. |] to construct an array directly if that's what you need):
let lemmas = [| for wt in Seq.zip words tags do // wt is tuple (string * string)
yield lemmatizer.lookup wt |]
Whether to use sequence expressions or not - that's just a personal preference. The first option seems to be more succinct in this case, but sequence expressions may be more readable for people less familiar with things like partial function application (in the shorter version using Seq.map)
how does one convert from a list of characters to a string?
To put it another way, how do I reverse List.ofSeq "abcd"?
UPDATE: new System.String (List.ofSeq "abcd" |> List.toArray) |> printfn "%A" seems to work fine, with or without new, but List.ofSeq "abcd" |> List.toArray) |> new System.String |> printfn "%A" fails. Why?
I asked a similar question once before. It seems object constructors aren't composable so you can't pass them as a function.
List.ofSeq "abcd" |> List.toArray |> (fun s -> System.String s) |> printfn "%A"
List.ofSeq "abcd" |> List.toArray |> (fun s -> new System.String(s)) |> printfn "%A"
Update
Constructors are first-class functions as of F# 4.0
List.ofSeq "abcd" |> List.toArray |> System.String |> printfn "%A"
Working with strings in F# is sometimes a bit uncomfortable. I would probably use the same code as Dario. The F# grammar doesn't allow using constructors as first class functions, so you unfortunately cannot do the whole processing in a single pipeline. In general, you can use static members and instance methods as first class functions, but not instance properties or constructors.
Anyway, there is a really nasty trick you can use to turn a constructor into a function value. I would not recommend actually using it, but I was quite surprised to see that it actually works, so I thought it may be worth sharing it:
let inline ctor< ^R, ^T
when ^R : (static member ``.ctor`` : ^T -> ^R)> (arg:^T) =
(^R : (static member ``.ctor`` : ^T -> ^R) arg)
This defines a function that will be inlined at compile time, which requires that the first type parameter has a constructor that takes a value of the second type parameter. This is specified as a compile-time constraint (because .NET generics cannot express this). Also, F# doesn't allow you to specify this using the usual syntax for specifying constructor constraints (which must take unit as the argument), but you can use the compiled name of constructors. Now you can write for example:
// just like 'new System.Random(10)'
let rnd = ctor<System.Random, _> 10
rnd.Next(10)
And you can also use the result of ctor as first-class function:
let chars = [ 'a'; 'b'; 'c' ]
let str = chars |> Array.ofSeq |> ctor<System.String, _>
As I said, I think this is mainly a curiosity, but a pretty interesting one :-).
Your approach:
new System.String (listOfChars |> List.toArray)
is the solution I usually end up with too.
F#'s grammar/type inference system simply seems unable to recognize a .NET constructor like new String as a curried function (which prevents you from using pipelining).
Just faced similar problem, and came up with this solutions:
List.fold (fun str x -> str + x.ToString()) "" (List.ofSeq "abcd")