F# deedle transform Series<string, obj> to Series<string, float>? - f#

If I get a row of Frame by using the .Rows.[rowIndex] operation, Deedle will return me an Object Series. Sometimes I know this only contains float. How do i convert all the obj into float series in on shot?

In Deedle series are generic, so ideally it should be possible to get a float series right away. But as the reasons why you get a series of Objects is not clear, you can still convert the values to floats by mapping an appropriate type casting function:
#load #"..\packages\Deedle.1.2.4\Deedle.fsx"
open Deedle
open System
// Let's prepare a sample series
let keys = ["1";"2";"3"]
let values = [1.1 :> Object;1.2 :> Object;1.3 :> Object]
let series = Series(keys, values)
// Now apply the map taking the Series<string,System.Object> series to Series<string,float>
series |> Series.map (fun _ v -> v :?> float)
// as #Foggy Finder pointed out, there is a convenience function to only map values
series |> Series.mapValues (fun v -> v :?> float)
// Alternatively, use the tryMap function that takes the Series<int,Object> series
// to Series<int,TryValue<float>>
series |> Series.tryMap (fun _ v -> v :?> float)
The type of the Series.map function is (('a -> 'b -> 'c) -> Series<'a,'b> -> Series<'a,'c>) when 'a : equality. This means that the first argument of the mapping function is the key which we ignore using the underscore as it is not needed to make the type cast. As Foggy Finder pointed out, there is a convenience function Series.mapValues that hides the keys.

Related

List.map with two function parameters, in F#

I came across this syntax:
[10.; 11.; 12.]
|> List.map (fun a b -> a * b)
in what case does List.map have two parameters (fun a b)?
This is the output in Jupyter Lab:
That's a fun example, because it looks confusing and usually doesn't come up in practice, so it caught me off-guard initially.
In short, what happens is you're mapping a list of floats into a list of float -> float functions. It's easier to see if you rewrite it as something like this:
let results =
[10.; 11.; 12.]
|> List.map (fun a -> (fun b -> a * b))
You pass a float -> float -> float function as the mapper, and it gets partially applied to the element from the input list. The second argument b is not being applied though, so the output of the mapping is a function that takes a float and multiplies it by the partially applied element of the list, and the overall result is a list of float -> float functions.
You can then apply those functions to some value like this:
results
|> List.map (fun f -> f 2.)

Set.union F# trouble

I have a Set<String*String>, and I'm trying to write a function that takes all the elements of that Set and return a Set<String>. My idea is to use Set.fold, and have an empty set accumulator and take the union of the two sets, but I'm running into problems. Here is the code:
type Chart = Set<Country*Country>;;
let countriesInChart (chart : Chart) =
Set.fold(fun (x,y) set -> Set.union [x;y] set ) chart []
But I get this error
Set.fold(fun (x,y) set -> Set.union [x;y] set ) chart [];;
--------------------------------^^^^^^^^^^^^^^^^^^^
error FS0001: This expression was expected to have type
'a * 'b
but here has type
Set<'c>
Look at your types and function signatures.
Set.fold takes a 'State -> 'T -> 'State as the folder function. 'State is the type that you're folding into and that will be the eventual return value, so in this case, you want it to be of type Set<Country>.
That means your lambda can't be right, because the first argument is a tuple. So we should probably switch the arguments of that lambda:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> Set.union [x;y] set ) chart []
Compiling that gives us
(96,39): error FS0001: This expression was expected to have type
Set<'a>
but here has type
'b list
(96,39) in this case is the Set.union function, and of course that is not used correctly, because it requires two sets, but we're passing it one set and a list. We can create a set from the list using Set.ofList:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) chart []
Again, we're getting a different error, so we're probably making progress:
(96,80): error FS0001: This expression was expected to have type
Set<(Country * Country) * (Country * Country)>
but here has type
'a list
(96,80) is the empty list at the end of the line - and of course, that's wrong, because the third argument to Set.fold needs to be Set<'T>. The set replacement for an empty list would be Set.empty, so let's go with that:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) chart Set.empty
It compiles! But as you found, it returns Set<Country * Country> instead of just Set<Country>.
Cases like this are when type inference makes it a little harder to see what's going on, so we should go ahead and add type annotations where we know exactly what the types need to be. The most obvious place is the return type of the function:
let countriesInChart (chart : Chart) : Set<Country> =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) chart Set.empty
Now the error is:
(96,74): error FS0001: Type mismatch. Expecting a
Set<Country>
but given a
Chart
The type 'Country' does not match the type 'Country * Country'
That error is for the second argument of Set.fold, and the reason is that once again, the arguments are in the wrong order. The signature of Set.fold is ('State -> 'T -> 'State) -> 'State -> Set<'T> -> 'State. If we look at what we already have, 'State in this case is Set<Country>, and 'T is Country * Country. That means Set.empty needs to be the second and chart the last argument, and so we arrive at
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) Set.empty chart
The most important rule of functional programming is this: Let the types guide you! ;-)
Try this one:
let f (chart: Chart) =
Set.fold (fun (x:Set<string>) (a,b) -> x |> Set.add a |> Set.add b) Set.empty chart
I'm not sure if the type annotation is necessary but it does force the output to be a Set<string>.

Value restriction woes

I was experimenting with an implementation of Clojure Transducers in F#, and quickly hit the dreaded Value Restriction error.
The whole point of Transducers is to be composable. This is some sample code:
type Reducer<'a,'b,'c> = ('a -> 'b -> 'a) -> 'a -> 'c -> 'a
module Transducers =
[<GeneralizableValue>]
let inline map proj : Reducer<'result,'output,'input> =
fun xf ->
fun result input ->
xf result (proj input)
let inline conj xs x = x :: xs
let inline toList xf input = List.fold (xf conj) [] input
let xform = map (fun i -> i + 9) >> map (fun a -> a * 5)
//let xs = toList xform [1;2] // if you apply this, type will be fixed to 'a list
// which makes xform unusable with eg 'a seq
Play on dotnetfiddle
GeneralizableValue was supposed to lift the value restriction, but does nothing, it seems. Your mission is to make this code compile without applying toList (Type inference will fix the type to 'a list, so you could not use the same xform with a seq) and without changing the type of xform (at least not in a way so as to make it not composable). Is this simply not possible in F#?
Why would annotating map with [<GeneralizableValue>] affect whether xform is subject to the value restriction? (in any case, map is already generalizable since it's defined by a lambda; also I don't see the point of all the inlines).
If your requirements are:
xform must be generic, but not an explicitly annotated type function
xform is defined by the application of an operator ((>>) in this case)
then you're out of luck; xform's body is not a generalizable expression (see ยง14.7 in the F# spec), so the value restriction applies here.
Furthermore, I would argue that this makes sense. Imagine that the value restriction didn't apply, and that we tweaked the definition of map:
let map proj : Reducer<_,_,_> =
printfn "Map called!"
fun xf result input ->
xf result (proj input)
Now enter these definitions one-by-one:
let xform<'a> : Reducer<'a,int,int> = map (fun i -> i + 9) >> map (fun a -> a * 5)
let x1 = xform (+)
let x2 = xform (*)
let x3 = xform (fun s i -> String.replicate i s)
When do you expect "Map called!" to be printed? Does the actual behavior match your expectations? In my opinion it's good that F# forces you to go out of your way to treat non-values as generic values.
So you're not going to get exactly what you want. But perhaps there's a different encoding that would work just as well for your use cases. If every reducer will be generic in the result type, then you could do this instead:
type Reducer<'b,'c> = abstract Reduce<'a> : ('a -> 'b -> 'a) -> 'a -> 'c -> 'a
module Transducers =
let map proj =
{ new Reducer<_,_> with
member this.Reduce xf result input = xf result (proj input) }
let (>!>) (r1:Reducer<'b,'c>) (r2:Reducer<'c,'d>) =
{ new Reducer<_,_> with
member this.Reduce xf result input = (r1.Reduce >> r2.Reduce) xf result input }
let conj xs x = x :: xs
let toList (xf:Reducer<_,_>) input = List.fold (xf.Reduce conj) [] input
let xform = map (fun i -> i + 9) >!> map (fun a -> a * 5)
Unfortunately, you've got to lift each operator like (>>) to the reducer level before you can use it, but this at least works for your example, since xform is no longer a generic value, but a non-generic value with a generic method.
What about annotating xform explicitly?
[<GeneralizableValue>]
let xform<'t> : Reducer<'t, _, _> = map (fun i -> i + 9) >> map (fun a -> a * 5) >> map (fun s -> s + 1)
As suggested above, and in the error message itself, can you add arguments explicitly?
let xform x = x |> map ...
F# only plays along so well with point free approaches

"summing" functions in F#

I have a list of functions in F# which are all of type (float -> float -> float -> float). I want to do some kind of fold on the sequence to get a single function which returns the sum of all of the functions.
For instance, I could pass the values 1.0, 2.0, and 3.0 to every function in the list, and get a return value from each one. Then I could compute the sum of all of these values. However, I want to generalize this.
I know how to do this recursively, but I feel like it should be doable in one line. Is there a concise way to accomplish this task?
The solution by #Lee is a one liner you're looking for. If you wanted to save a few characters, you can use List.sumBy which first applies a given function to an element of the list (similar to List.map) and then sums the result (just like List.sum):
let sumAll (fs:(_ -> _ -> _ -> float) list) a b c =
List.sumBy (fun f -> f a b c) fs
Both this and Lee's version uses type annotations to specify that the functions in the list return float. This is needed, because otherwise the compiler does not know what kind of numbers you want to sum using List.sum (floats, integers, etc.). This ambiguity needs to be resolved to compile the function.
Alternatively, you could mark the function as inline and then it would be inlined when you call it (and it would work for multiple different numeric types). You can also pass the fs parameter as the last one and use partial function application:
let inline sumAll a b c = List.sumBy (fun f -> f a b c)
Now you can call it using pipelining as follows: fs |> sumAll 1 2 3.
let sumAll (fs: (float -> float -> float -> float) list) a b c = List.map (fun f -> f a b c) fs |> Seq.sum
The answers by #Lee and #Tomas are great, but there is a shorter way.
If you can afford passing (a, b, c) as a triple upon invocation:
let inline sumAll() = (|||>) >> List.sumBy
// usage
let predicates =
[
fun a b c -> a
fun a b c -> b * 42.0 - c
]
let ret1 = predicates |> sumAll()(1.0, 2.0, 3.0)
It will be also generic:
let predicates2 =
[
fun a b c -> c - 10
fun a b c -> a + c * 42
]
let ret2 = predicates2 |> sumAll()(1, 2, 3)
A more readable way which supports curried arguments:
let sumAllCurried a b c = (a,b,c) |> (|||>) |> List.sumBy<_, float>
// usage
let ret3 = predicates |> sumAllCurried 1.0 2.0 3.0
Note, I'm using a type parameter on List.sumBy since it looks shorter than typing an entire type specification for f.

Scaling a sequence in F#

I am trying to scale a sequence by the first element of the sequence, so the first element will always be one, and then subsequent elements are a ratio of the first element to the nth element of the original sequence.
Here is my code,
open System
open System.Collections
let squish1 (x:Double seq) =
let r = (Seq.head x:Double)
Seq.fold (fun (xi:Double) (r:Double) -> xi/r);;
And I test on this little vector:-
squish1 [|5.0; 1.0; 1.0; 1.0; 1.0; 1.0|];;
I have typed everything because I get this error message
normaliseSequence.fsx(9,1): error FS0030: Value restriction. The value 'it' has been >inferred to have generic type
val it : (Double -> '_a -> Double) when '_a :> seq
Either make the arguments to 'it' explicit or, if you do not intend for it to be generic, >add a type annotation.
But clearly I am misunderstanding because I get the error message even with everything typed. What am I missing?
Any and all advice gratefully received. Thanks
fold expects two more parameters, the seed value and the sequence. This works:
let squish1 (x:Double seq) =
let r = (Seq.head x:Double)
Seq.fold (fun (xi:Double) (r:Double) -> xi/r) 0.0 x
However, I'm guessing you probably want map instead of fold:
let squish1 (x:Double seq) =
let r = (Seq.head x:Double)
Seq.map (fun (xi:Double) -> xi/r) x
Incidentally, I would probably write it this way:
let inline squish1 (x:seq<_>) =
let r = Seq.head x
Seq.map (fun n -> n / r) x
Now it works for all types that support division.

Resources