Is there better way how to do this? :
let intOption = Some(123)
let longOption = match intOption with
| Some x -> Some(int64 x )
| None -> None
I need to convert option of int to option of int64.
Option.map does exactly what you need.
intOption |> Option.map int64
The function you're looking for is Option.map:
let longOption = Option.map int64 intOption
Related
The built-in conversion operators in F# eliminate units of measure. I'd like to define ones that preserve them. I can do it fine for one specific conversion, e.g. int to float:
let inline intToFloat (x:int<'u>) =
x |> float |> LanguagePrimitives.FloatWithMeasure<'u>
But I don't know what would be the syntax for a generic ((anything with an op_Implicit ^m -> float) -> float) operator:
let inline floatM (x:^m<'u>) =
x |> float |> LanguagePrimitives.FloatWithMeasure<'u>
// FS0712: Type parameter cannot be used as type constructor
Is it possible at all to do this?
I did it as such:
let inline toIntWithMeasure<[<Measure>] 'a> (x:obj) =
match x with
| :? int as i -> i |> LanguagePrimitives.Int32WithMeasure<'a>
| _ -> failwith "Not an int!"
A workaround is to use overloading rather than generics:
type Conv =
static member inline toDouble<[<Measure>] 'u> (x: float32<'u>) =
x |> float |> LanguagePrimitives.FloatWithMeasure<'u>
static member inline toDouble<[<Measure>] 'u> (x: sbyte<'u>) =
x |> float |> LanguagePrimitives.FloatWithMeasure<'u>
static member inline toDouble<[<Measure>] 'u> (x: int16<'u>) =
x |> float |> LanguagePrimitives.FloatWithMeasure<'u>
static member inline toDouble<[<Measure>] 'u> (x: int<'u>) =
x |> float |> LanguagePrimitives.FloatWithMeasure<'u>
static member inline toDouble<[<Measure>] 'u> (x: int64<'u>) =
x |> float |> LanguagePrimitives.FloatWithMeasure<'u>
And now:
let f = Conv.toDouble (45<second>) // f is a float<second>
I'd love to be able to declare an operator to hide away the static class, something like:
let inline floatM< ^m, [<Measure>]'u when (^m) : (static member toFloat: ^m<'u> -> float<'u>)> (x:^m) =
Conv.toDouble x
But that still runs into the same limitation that a generic type cannot have a generic unit of measure.
I'll accept my own answer until someone comes up with a better solution.
I asked this question last week regarding seq<float option> values passed to RProvider. I had hoped that I'd be able to apply the accepted answer there to other option types in F#. Unfortunately, NaN is only applicable to numeric in R.
How can I convert a None string in F# to NA and pass to R?
You can use Option.toObj.
For example:
let l1 = [ Some "x"; None; Some "y"]
let l2 = l1 |> List.map (Option.toObj)
// val l2 : string list = ["x"; null; "y"]
And you can use Option.toNullable for number values, but it would convert to type Nullable<float>, and None would also be null. For some reason this doesn't work the other way round:
let l3 = l2 |> List.map (Option.ofObj)
// val l3 : string option list = [Some "x"; null; Some "y"]
I don't know if that's intended or a bug.
Edit : Option.ofObj does work properly. F# Interactive displays None as null when it is in a list for some reason.
The answer to your previous question is still applicable. You can use null to indicate a missing string value:
let optString = ["x"; null; "y"]
let testData5 =
namedParams [
"optString", optString;]
|> R.data_frame
Gives me:
val testData5 : SymbolicExpression =
optString
1 x
2 <NA>
3 y
You can convert the option string to just string list:
let optString2 = [Some "x"; None; Some "y"]
optString2
|> List.map (fun x -> match x with
| Some x -> x
| None -> null)
I'm looking to make a function that handles a seq of any numeric type of data (int, float, double), does a little computation on it via mapping, then does a summation of these calculated values. The problem I am running into is that Seq.sum (or really just '(+)' in general) causes the type parameters to be integer, or just give a flat out error. It seems there there should be a way to make this work by using type constraints but I can't seem to get it.
type ValueWithComputation<'v> = {Value: seq<'v>; Computation: 'v -> 'v}
let calculateAndCombine (x: ValueWithComputation<'v>) =
x.Value
|> Seq.map x.Computation
|> Seq.sum // sometimes gives error: "Could not resolve the ambiguity inherent in the use of operator '(+)'
let x = {Value= {1..10}; Computation= (fun x->x*2)}
let y = {Value= {(1.0)..(10.0)}; Computation= (fun x->x*x)}
let totalX = calculateAndCombine x //this causes the code force 'v to be int
let totalY = calculateAndCombine y //gives an error since this isn't an int
This seems similar to F# generics / function overloading syntax but it didn't really explain how to get it to work for all value types.
I got it to work like this. Read the answer linked by Foggy Finder. Then you need additionally the static member Zero for the sum to work.
type ValueWithComputation< ^T when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member Zero: ^T)> =
{ Value: seq< ^T>
Computation: ^T -> ^T }
let inline calculateAndCombine x =
x.Value
|> Seq.map x.Computation
|> Seq.sum
let x = {Value= {1..10}; Computation= (fun x->x*2)}
let y = {Value= {(1.0)..(10.0)}; Computation= (fun x->x*x)}
let totalX = calculateAndCombine x
let totalY = calculateAndCombine y
I am having trouble with the following:
let safeDiv x y =
match (x,y) with
| (_, Some 0) -> None
| (Some xx, Some yy) -> Some (xx/yy)
| _ -> None
When I go to run this simple function in the interactive window of Visual Studio like so:
safeDiv 4 2
I get the following error...
This expression was expected to have type int option but here has type int.
Could it be I'm meant to use safeDiv Some(4) Some(2)? This doesn't work either...
Ok, this is overkill but I actually did something similar to this recently.
First I defined a computation expression builder for the option type:
type OptionBuilder() =
member this.Bind(x, f) = Option.bind f x
member this.Return(x) = Some x
member this.ReturnFrom(x) = x
let opt = new OptionBuilder()
And then I defined a function sub of type float -> float -> float option
let sub x y = if y = 0.0 then None else Some (x / y)
And finally I used the OptionBuilder to define saveDiv as float option -> float option -> float option
let safeDiv x y = opt { let! a = x
let! b = y
return! sub a b }
You can read more about computation expressions on wikibooks: http://en.wikibooks.org/wiki/F_Sharp_Programming/Computation_Expressions
And if you want to dive deeper into the theory behind this, you can read this paper by Tomas Petricek and Don Syme: http://www.cl.cam.ac.uk/~tp322/drafts/notations.pdf
Your second version was close.
It should be
safeDiv (Some(4)) (Some(2))
The extra brackets are required to make sure that functions are applied in the correct order.
You constructed a function that has the signature safeDiv : int option -> int option -> int option. You need to use an entry like safeDiv (Some 4) (Some 2) to use your function as is.
The problem is in the matching of (4, 2), of type int*int, with the expressions (_, Some 0) and (Some xx, Some yy). The whole function can be simplified:
let safeDiv x y =
match (x,y) with
| (_, 0) -> None
| (_, _) -> Some (x/y)
Making the following call valid
safeDiv 4 2
How come that I can do:
let printTeams x : unit =
let rnd = new Random()
Seq.toList x |> List.sortBy (fun x -> rnd.Next()) |> printTeams'
but not:
let printTeams x : unit =
let rnd = new Random()
printTeamsRec' <| Seq.toList x <| List.sortBy(fun x -> rnd.Next())
I'm just getting an error on the last one, which says:
Type mismatch. Expecting a string
list -> 'a -> 'b but given a
string list -> unit The type ''a
-> 'b' does not match the type 'unit'
The error occures on the third line at printTeamsRec'
Any help would be appreciate.
Two things: the translation of the forward pipe to backwards pipe is incorrect, and precedence is different.
let printTeams x : unit =
let rnd = new Random()
printTeamsRec' <| (List.sortBy(fun x -> rnd.Next()) <| Seq.toList x)