How can I do an "inline match" in F# - f#

I have a function
let binaryOp load store op =
(load 0, load 1) ||> op |> store 2
that reads 2 values from a virtual memory, applies a binary operation on them, and writes the result back to memory. The argument's types are:
load: (int -> 'a)
op: ('a -> int)
store: (int -> unit)
As you can see op is restricted to return an int. I want to change that so op can return anything that can be converted to an int. This wouldn't be a problem usually as I could just do
(load 0, load 1) ||> op |> int |> store 2
Problem is, I want to support custom conversions too, specifically bool to int which are resolved at compile time. Something like this
let inline toInt (x: ^a) =
inline match x with
| :? bool as b -> if b then 1 else 0
| _ -> int x
let inline binaryOp load store op =
(load 0, load 1) ||> op |> toInt |> store 2
where the correct match arm is resolved at compile time and directly inlined at call site. I've chosen inline match for illustration purposes, but I'm fine with anything that solves my actual problem.
Is something like this possible in F#?

Related

How extract the int from a FsCheck.Gen.choose

I'm new on F#, and can't see how extract the int value from:
let autoInc = FsCheck.Gen.choose(1,999)
The compiler say the type is Gen<int>, but can't get the int from it!. I need to convert it to decimal, and both types are not compatible.
From a consumer's point of view, you can use the Gen.sample combinator which, given a generator (e.g. Gen.choose), gives you back some example values.
The signature of Gen.sample is:
val sample : size:int -> n:int -> gn:Gen<'a> -> 'a list
(* `size` is the size of generated test data
`n` is the number of samples to be returned
`gn` is the generator (e.g. `Gen.choose` in this case) *)
You can ignore size because Gen.choose ignores it, as its distribution is uniform, and do something like:
let result = Gen.choose(1,999) |> Gen.sample 0 1 |> Seq.exactlyOne |> decimal
(* 0 is the `size` (gets ignored by Gen.choose)
1 is the number of samples to be returned *)
The result should be a value in the closed interval [1, 999], e.g. 897.
Hi to add to what Nikos already told you, this is how you can get an decimal between 1 and 999:
#r "FsCheck.dll"
open FsCheck
let decimalBetween1and999 : Gen<decimal> =
Arb.generate |> Gen.suchThat (fun d -> d >= 1.0m && d <= 999.0m)
let sample () =
decimalBetween1and999
|> Gen.sample 0 1
|> List.head
you can now just use sample () to get a random decimal back.
In case you just want integers between 1 and 999 but have those converted to decimal you can just do:
let decimalIntBetween1and999 : Gen<decimal> =
Gen.choose (1,999)
|> Gen.map decimal
let sampleInt () =
decimalIntBetween1and999
|> Gen.sample 0 1
|> List.head
what you probably really want to do instead
Is use this to write you some nice types and check properties like this (here using Xunit as a test-framework and the FsCheck.Xunit package:
open FsCheck
open FsCheck.Xunit
type DecTo999 = DecTo999 of decimal
type Generators =
static member DecTo999 =
{ new Arbitrary<DecTo999>() with
override __.Generator =
Arb.generate
|> Gen.suchThat (fun d -> d >= 1.0m && d <= 999.0m)
|> Gen.map DecTo999
}
[<Arbitrary(typeof<Generators>)>]
module Tests =
type Marker = class end
[<Property>]
let ``example property`` (DecTo999 d) =
d > 1.0m
Gen<'a> is a type that essentially abstracts a function int -> 'a (the actual type is a bit more complex, but let's ignore for now). This function is pure, i.e. when given the same int, you'll get the same instance of 'a back every time. The idea is that FsCheck generates a bunch of random ints, feeds them to the Gen function, out come random instances of the type 'a you're interested in, and feeds those to a test.
So you can't really get out the int. You have in your hands a function that given an int, generates another int.
Gen.sample as described in another answer essentially just feeds a sequence of random ints to the function and applies it to each, returning the results.
The fact that this function is pure is important because it guarantees reproducibility: if FsCheck finds a value for which a test fails, you can record the original int that was fed into the Gen function - rerunning the test with that seed is guaranteed to generate the same values, i.e. reproduce the bug.

How to check the case of a discriminated union with FsUnit?

I'd like to check that a value is of a particular case of a discriminated union, without having to also check any included data. My motivation is to only test one thing with each unit test.
An example is as follows (the last two lines give compilation errors):
module MyState
open NUnit.Framework
open FsUnit
type MyState =
| StateOne of int
| StateTwo of int
let increment state =
match state with
| StateOne n when n = 10 -> StateTwo 0
| StateOne n -> StateOne (n + 1)
| StateTwo n -> StateTwo (n + 1)
[<Test>]
let ``incrementing StateOne 10 produces a StateTwo`` ()=
let state = StateOne 10
(increment state) |> should equal (StateTwo 0) // works fine
(increment state) |> should equal (StateTwo _) // I would like to write this...
(increment state) |> should be instanceOfType<StateTwo> // ...or this
Can this be done in FsUnit?
I'm aware of this answer but would prefer not to have to write matching functions for each case (in my real code there are far more than two).
If you don't mind using reflections, the isUnionCase function from this answer could be handy:
increment state
|> isUnionCase <# StateTwo #>
|> should equal true
Note that it's a bit verbose because you need a function call before comparing values.
A similar but lighter approach could be comparison of tags:
// Copy from https://stackoverflow.com/a/3365084
let getTag (a:'a) =
let (uc,_) = Microsoft.FSharp.Reflection.FSharpValue.GetUnionFields(a, typeof<'a>)
uc.Name
increment state
|> getTag
|> should equal "StateTwo"
Beware that this is not type-safe and you can easily misspell a union case name.
What I would do is to create a similar DUs for comparison purpose:
type MyStateCase =
| StateOneCase
| StateTwoCase
let categorize = function
| StateOne _ -> StateOneCase
| StateTwo _ -> StateTwoCase
In this way, you define categorize once and use it multiple times.
increment state
|> categorize
|> should equal StateTwoCase
It appears FSUnit doesn't (or can't, I'm not sure) directly support this use case.
The next best thing I've found is to declare a TestResult type like the following and use a match to reduce the result to this type.
type TestResult =
| Pass
| Fail of obj
Here is the reducing match
let testResult =
match result with
| OptionA(_) -> Pass
| other -> Fail(other)
Now you can just use should equal to ensure the correct result.
testResult |> should equal Pass
The benefits of this solution are strong typing but more importantly in the failure case you can see what the invalid result was.
It doesn't look very elegant, but you can extract type from a value of state:
let instanceOfState (state: 'a) =
instanceOfType<'a>
And then use it in the test:
(increment state) |> should be (instanceOfState <| StateTwo 88)
EDIT
Yes, unfortunately the type is always MyState. Looks like pattern matching or ugly reflection are inevitable.
What if FsUnit already supports an assertion against a specific union case, albeit one restricted to values of the type Microsoft.FSharp.Core.Choice<_,...,_>?
Let's leverage this with a multi-case active pattern, which uses Reflection to check against the union case name.
open System.Reflection
open Microsoft.FSharp.Reflection
let (|Pass|Fail|) name (x : obj) =
let t = x.GetType()
if FSharpType.IsUnion t &&
t.InvokeMember("Is" + name,
BindingFlags.GetProperty, null, x, null )
|> unbox then Pass
else Fail x
Should be working now:
increment state
|> (|Pass|Fail|) "StateTwo"
|> should be (choice 1)

"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.

Exception handling in point-free functions

I'm stuck with a seemingly trivial problem: I'm unable to handle an exception in a function if it's written in a point-free manner.
Consider these two functions:
let divide1 x y =
try
x / y
with
| :? System.DivideByZeroException -> 42
let divide2 =
try
(/)
with
| :? System.DivideByZeroException -> fun _ _ -> 42
let x1 = divide1 5 0 // works fine
let x2 = divide2 5 0 // doesn't handle an exception
Although both functions are seemingly same, they have different types:
val divide1: int -> int -> int
val divide2: (int -> int -> int)
Obviously, divide2 does not even attempt to handle an exception. It simply returns an operator.
What can I do in order to make divide2 handle the exception in a proper manner (except specifically declaring its arguments)?
This is one of the reasons why I find the point-free style problematic. It makes it difficult to use standard language constructs like try .. with (or standard loops and other F# features) and you need to replace them with custom combinators. In this case, you could define combinator tryWith2 that wraps a two-argument function in an exception handler:
let tryWith2 f h a b =
try f a b // Call the function with two arguments
with e ->
// Try running the error handler with the exception
match h e with
| Some g -> g a b // Error handler provided another function
| _ -> reraise() // Error was not handled - reraise
Then you could write the function in a point-free style like this (the error handling is still not-point-free, but I do not want to make this too silly :-))
let divide2 =
tryWith2 (/) (function
| :? System.DivideByZeroException -> Some(fun _ _ -> 42)
| _ -> None)
let x1 = divide2 5 0 // returns 42
let x2 = divide2 5 1 // returns 5
Of course, the point free style is useful, even in F#. For example, when writing a DSL, it is a great way to compose declarative specification (because the primitives express something using higher-level of abstraction). Here, you need to express something that is quite close to normal F# code and, I believe, that is best expressed as normal F# code.
What you need to remember is that in divide2, you aren't returning the result of X divided by Y, you're returning a function that divides X by Y. The code for the let binding is being executed immediately because it isn't given function syntax. Let's look at both divide bindings with the longer function syntax:
let divide1 =
fun x ->
fun y ->
try
x / y
with
| :? System.DivideByZeroException -> 42
let divide2 =
try
fun x ->
fun y ->
x / y
with
| :? System.DivideByZeroException -> fun _ _ -> 42
When displayed this way, it should be clearer how the two definitions are different. The try block is in a completely different location, and executed at different points in time.
The only way to add logic such as exception handling to an existing function is to wrap it, either as you do in divide1, or with a higher order function as Tomas has shown.

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