I'm trying to use Math.Round within a function to round a monetary amount as follows:
let calculateTaxablePayToDate previousPayToDate taxablePayThisMonth =
taxablePayThisMonth
|> fun (x:decimal) -> Math.Round(x)
|> fun x -> x + previousPayToDate
The types that I'm passing in are both of type decimal<GBP>. When I try and run them through the function though I get:
This expression was expected to have type
decimal but here has type
int<GBP>
How am I able to use Math.Round on a figure that has a Unit of Measure attached?
Math.Round expects a raw value, not a measure value. You can wrap it in a function generic in the measure type:
open System
open Microsoft.FSharp.Core.LanguagePrimitives
let roundMeasure<[<Measure>]'u>(x: decimal<'u>): decimal<'u> = Math.Round(decimal x) |> DecimalWithMeasure
you should then be able to do:
let calculateTaxablePayToDate previousPayToDate taxablePayThisMonth =
taxablePayThisMonth |> roundMeasure |> fun x -> x + previousPayToDate
or
let calculateTaxablePayToDate previousPayToDate taxablePayThisMonth =
previousPayToDate + (roundMeasure taxablePayThisMonth)
Related
I'm trying to explore the dynamic capabilities of F# for situations where I can't express some function with the static type system. As such, I'm trying to create a mapN function for (say) Option types, but I'm having trouble creating a function with a dynamic number of arguments. I've tried:
let mapN<'output> (f : obj) args =
let rec mapN' (state:obj) (args' : (obj option) list) =
match args' with
| Some x :: xs -> mapN' ((state :?> obj -> obj) x) xs
| None _ :: _ -> None
| [] -> state :?> 'output option
mapN' f args
let toObjOption (x : #obj option) =
Option.map (fun x -> x :> obj) x
let a = Some 5
let b = Some "hi"
let c = Some true
let ans = mapN<string> (fun x y z -> sprintf "%i %s %A" x y z) [a |> toObjOption; b |> toObjOption; c |> toObjOption]
(which takes the function passed in and applies one argument at a time) which compiles, but then at runtime I get the following:
System.InvalidCastException: Unable to cast object of type 'ans#47' to type
'Microsoft.FSharp.Core.FSharpFunc`2[System.Object,System.Object]'.
I realize that it would be more idiomatic to either create a computation expression for options, or to define map2 through map5 or so, but I specifically want to explore the dynamic capabilities of F# to see whether something like this would be possible.
Is this just a concept that can't be done in F#, or is there an approach that I'm missing?
I think you would only be able to take that approach with reflection.
However, there are other ways to solve the overall problem without having to go dynamic or use the other static options you mentioned. You can get a lot of the same convenience using Option.apply, which you need to define yourself (or take from a library). This code is stolen and adapted from F# for fun and profit:
module Option =
let apply fOpt xOpt =
match fOpt,xOpt with
| Some f, Some x -> Some (f x)
| _ -> None
let resultOption =
let (<*>) = Option.apply
Some (fun x y z -> sprintf "%i %s %A" x y z)
<*> Some 5
<*> Some "hi"
<*> Some true
To explain why your approach does not work, the problem is that you cannot cast a function of type int -> int (represented as FSharpFunc<int, int>) to a value of type obj -> obj (represented as FSharpFunc<obj, obj>). The types are the same generic types, but the cast fails because the generic parameters are different.
If you insert a lot of boxing and unboxing, then your function actually works, but this is probably not something you want to write:
let ans = mapN<string> (fun (x:obj) -> box (fun (y:obj) -> box (fun (z:obj) ->
box (Some(sprintf "%i %s %A" (unbox x) (unbox y) (unbox z))))))
[a |> toObjOption; b |> toObjOption; c |> toObjOption]
If you wanted to explore more options possible thanks to dynamic hacks - then you can probably do more using F# reflection. I would not typically use this in production (simple is better - I'd just define multiple map functions by hand or something like that), but the following runs:
let rec mapN<'R> f args =
match args with
| [] -> unbox<'R> f
| x::xs ->
let m = f.GetType().GetMethods() |> Seq.find (fun m ->
m.Name = "Invoke" && m.GetParameters().Length = 1)
mapN<'R> (m.Invoke(f, [| x |])) xs
mapN<obj> (fun a b c -> sprintf "%d %s %A" a b c) [box 1; box "hi"; box true]
I have asked a related question here. I want to do a similar thing but this time thread an accumulator though the array of functions. I immediately thought of Array.Reduce or Array.Fold but they are not working for me:
let AddTen x =
x + 10
let MultiplyFive x =
x * 5
let SubtractTwo x =
x - 2
let functionArray = [| AddTen; MultiplyFive; SubtractTwo |]
let calculateAnswer functionArray x = functionArray |>Array.reduce(fun acc f -> f acc)
The last line throws this exception:
Type mismatch. Expecting a
'a -> 'b but given a
'b The resulting type would be infinite when unifying ''a' and ''b -> 'a'
Am I thinking about the problem incorrectly?
Take a look at these two:
let calculateReduce = functionArray |> Array.reduce (fun f g -> f >> g)
let calculateFold x = functionArray |> Array.fold (fun acc f -> f acc) x
In the reduce version, you take an array of functions and compose them into a single function which you can later call on x.
In the fold version you fold over the array of functions, threading the accumulator through and applying each function to it in sequence. x is the initial value of the accumulator here.
Your original code didn't work, because a reduce expects a 'a -> 'a -> 'a function, which in case of an array of functions would imply composition, while you were trying to apply one function of type int -> int to another.
If the pipe operator is created like this:
let (|>) f g = g f
And used like this:
let result = [2;4;6] |> List.map (fun x -> x * x * x)
Then what it seems to do is take List.Map and puts it behind (fun x -> x * x * x)
And doesn't change anything about the position of [2;4;6]
So now it looks like this:
let result2 = [2;4;6] (fun x -> x * x * x) List.map
However this doesn't work.
I am just learning f# for the first time now. And this bothered me while reading a book about f#. So I might learn what I'm missing later but I decided to ask anyway.
It is obvious though that I am missing something major. Since I can easily recreate the pipe operator. But I don't get why it works. I might embarrass myself very soon as I learn more. Oh well.
The pipe operator is simply syntactic sugar for chained method calls. It's very similar to how linq expressions are expressed in C#.
Explanation from here:
Forward Pipe Operator
I love this guy. The Forward pipe operator is simply defined as:
let (|>) x f = f x
And has a type signature:
'a -> ('a -> 'b) -> 'b
Which translates to: given a generic type 'a, and a function which takes an 'a and returns a 'b, then return the application of the function on the input.
Rather than explaining this, let me give you an example of where it can be used:
// Take a number, square it, then convert it to a string, then reverse that string
let square x = x * x
let toStr (x : int) = x.ToString()
let rev (x : string) = new String(Array.rev (x.ToCharArray()))
// 512 -> 1024 -> "1024" -> "4201"
let result = rev (toStr (square 512))
The code is very straight forward, but notice just how unruly the syntax looks. All we want to do is take the result of one computation and pass that to the next computation. We could rewrite it by introducing a series of new variables:
let step1 = square 512
let step2 = toStr step1
let step3 = rev step2
let result = step3
But now you need to keep all those temporary variables straight. What the (|>) operator does is take a value, and 'forward it' to a function, essentially allowing you to specify the parameter of a function before the function call. This dramatically simplifies F# code by allowing you to pipe functions together, where the result of one is passed into the next. So to use the same example the code can be written clearly as:
let result = 512 |> square |> toStr |> rev
Edit:
In F# what you're really doing with a method call is taking a function and then applying it to the parameter that follows, so in your example it would be List.map (fun x -> x * x * x) is applied to [2;4;6]. All that the pipe operator does is take the parameters in reverse order and then do the application reversing them back.
function: List.map (fun x -> x * x * x)
parameter: [2;4;6]
Standard F# call syntax: f g
Reversed F# call syntax: g f
Standard:
let var = List.map (fun x -> x * x * x) [2;4;6]
Reversed:
let var = [2;4;6] |> List.map (fun x -> x * x * x)
The brackets around |> mean it is an infix operator so your example could be written
let result = (|>) [2;4;6] (List.map (fun x -> x * x * x))
Since |> applies its first argument to the second, this is equivalent to
let result = (List.map (fun x -> x * x)) [2;4;6]
As others have said above, basically you're misunderstanding what result2 would resolve to. It would actually resolve to
List.map (fun x -> x * x * x) [2;4;6]
List.map takes two arguments: a function to apply to all elements in a list and a list. (fun x -> x * x * x) is the first argument and [2;4;6] is the second.
Basically just put what's on the left of |> after the end of what's on the right.
If you enter your definition of |> into fsi and look at the operator's signature derived by type inference you'll notice val ( |> ) : 'a -> ('a -> 'b) -> 'b, i.e. argument 'a being given to function ('a -> 'b) yields 'b.
Now project this signature onto your expression [2;4;6] |> List.map (fun x -> x * x * x) and you'll get List.map (fun x -> x * x * x) [2;4;6], where the argument is list [2;4;6] and the function is partially applied function of one argument List.map (fun x -> x * x * x).
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.
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)