Trying to understand F# active patterns, why can I do this: - f#

I have a Dictionary over which I initially iterated thusly:
myDictionary |> Seq.iter (fun kvp -> doSomething kvp.Key kvp.Value)
Later, I discovered that I could make use of the KeyValue active pattern, and do this:
myDictionary |> Seq.iter (fun (KeyValue (k, v)) -> doSomething k v)
Knowing that active patterns aren't some form of preprocessor directive, how am I able to substitute the kvp argument in the lambda for a function that decomposes it?

Functions arguments call always be destructured using pattern matching. For instance:
let getSingleton = fun [x] -> x
let getFirst = fun (a,b) -> a
let failIfNotOne = fun 1 -> ()
let failIfNeitherOne = fun (x,1 | 1,x) -> ()
Semantically, fun<pat>-><body> is roughly equivalent to
fun x -> match x with |<pat>-><body>
| _ -> raise MatchFailureException(...)

I think the answer from #kvb covers in enough details why you can use patterns in the arguments of fun. This is not an ad-hoc feature - in F#, you can use patterns anywhere where you can bind a variable. To show some of the examples by #kvb in another contexts:
// When declaring normal functions
let foo [it] = it // Return the value from a singleton list
let fst (a, b) = a // Return first element of a pair
// When assigning value to a pattern using let
let [it] = list
let (a, b) = pair
Similarly, you can use patterns when writing fun. The match construct is a bit more powerful, because you can specify multiple clauses.
Now, active patterns are not really that magical. They are just normal functions with special names. The compiler searches for active patterns in scope when it finds a named pattern. For example, the pattern you're using is just a function:
val (|KeyValue|) : KeyValuePair<'a,'b> -> 'a * 'b
The pattern turns a KevValuePair object into a normal F# tuple that is then matched by a nested pattern (k, v) (which assigns the first element to k and the second to v). The compiler essentially translates your code to:
myDictionary |> Seq.iter (fun _arg0 ->
let _arg1 = (|KeyValue|) _arg0
let (k, v) = _arg1
doSomething k v )

Related

implementing an equivalent of the C#'s null test in F#

I'm using quite a lot this piece of code:
let inline (||>) (a: 'a option) (b: 'a -> unit) = if a.IsSome then b a.Value
so I can do things like
myData ||> DoSomethingWithIt
without having to test if myData is Some or None since there are many functions that don't generally need to test for an option. This avoid to put the test in the function itself.
I would like to extend this to methods of a type where I could do like C#'s:
myData?.DoSomethingWithIt
essentially replacing:
if myData.IsSome then myData.Value.DoSomethingWithIt
with some syntactic sugar.
but I have no idea how I could do the operator so that it allows to get access to the type's method in the expression. Is that possible in F#?
I'm also open to learn about why it could be a bad idea if it is :)
Depending on your return type of DoSomethingWithIt the F# library offers a few standard functions for working with Options that can be turned into operators.
let x = Some 1
let aPrinter a = printfn "%i" a
let add1 a = a + 1
let (|?>) opt f = Option.iter f opt
let (|??>) opt f = Option.map f opt
x |?> aPrinter
let y = x |??> add1
You can also consider redefining your DoSomethingWithIt to work with an option by partial application.
let DoSomethingWithIt' = Option.iter DoSomethingWithIt
let something' = Option.iter (fun (b:B) -> b.DoSomethingWithIt()) //For instance methods
That may end up being a lot of work depending how many functions you are dealing with.
Ultimately you shouldn't try to hide the fact you are working with Options. By making something an Option you are telling the compiler that you aren't sure whether it exists or not. It is trying to help you by forcing you to deal with the None case. If there are lots of cases in your code where you know your Option is Some then there's probably a larger architectural issue in your code and you should try to lift all your Option<'T> to just T prior to doing work with them. e.g.:
let lift xs =
[
for x in xs do
match x with
| Some x -> yield x
| None -> ()
]
Have a look at Option.iter. It has the same signature as your operator.
There is no analogical syntax for such constructions but F# have alternatives.
The easiest way is to use FSharpx.Extras library and FSharpx.Option.maybe computation expression which will allow you to use Option related operations.
open FSharpx.Option
let a = Some 1
let b = maybe {
let! v = a
return v + 3
} // b is (Some 4)
let c : int option = None
let d = maybe {
let! v = c
return v + 3 // this line won't be reached
} // d is None
I believe that the ?. operator in c# is a syntactic sugar that hides the if statement checking for null before invoking a member of the type. Even if you could make it work the way you plan, I feel that it would go against the FP principles and could cause more problems down the line.
The Option module contains probably most of what you need already. The iter function allows to call a function on the value of the Option if that value is present (Some).
If you have situation that your input parametes can be nulls, but not options, you can use the Option.ofObj function that will convert the parameter to an Option with Some if the parameter is not null, else None.
So assuming that your function DoSomethingWithit accepts a string and returns unit:
let DoSomethingWithIt = //(string -> unit)
printf "%s; "
You can use this more verbose syntax to (for example) iterate over nullable values in your list:
let lst = [ "data"; "data 2"; null; "data3" ]
lst
|> List.iter (fun v -> v |> Option.ofObj |> Option.iter DoSomethingWithIt)
Alternatively you can compose the Optioni.ofObj and Option.iter DoSomethingWithIt functions and do something like
let SafeDoSomethingWithIt = //(string -> unit)
Option.ofObj >> Option.iter DoSomethingWithIt
This gives you safe invocation:
let lst2 = [ "data"; "data 2"; null; "data3" ]
lst2
|> List.iter SafeDoSomethingWithIt
You can generalize the combination of the functions returning unit (but not only)
let makeSafe fn =
Option.ofObj >> Option.iter fn
Then you can create a series of safe functions:
let SafeDoSomethingWithIt = makeSafe DoSomethingWithIt
let safePrint = makeSafe (printf "%s; ")
//...etc
Then this still works:
lst2
|> List.iter SafeDoSomethingWithIt
lst2
|> List.iter safePrint
You can also write a wrapper for functions returning values using Option.bind function.
let makeSafeReturn fn = //(string -> string option)
Option.ofObj >> Option.bind fn

How to do null-conditional using Option.map? And how can F# get the property of an null object? Bug?

The following code returns Some "Test" stead of None. Basically, I'm trying to implement the C# code of cObj?.B.A.P.
// Setup
[<AllowNullLiteral>]
type A() =
member x.P = "Test"
[<AllowNullLiteral>]
type B(a:A) =
member x.A = a
[<AllowNullLiteral>]
type C(b:B) =
member x.B = b
// Test
let aObj: A = null
let cObj = new C(new B(aObj))
let r =
cObj |> Option.ofObj
|> Option.map(fun c -> c.B)
|> Option.map(fun b -> b.A)
|> Option.map(fun a -> a.P) // Expect return None since a is null
// printfn "%A" a; will print <null>.
// How can F# got property of null object?
r
It seems F# doesn't treat null as None in the Option.map. Is there a simple fix to make it return None as soon as a null is found?
F#, unlike C#, tries to be explicit everywhere. In the long run this leads to more maintainable and correct programs.
In particular, null has absolutely nothing to do with Option. null is not the same as None. None is a value of type Option, while null is this very vague concept - a value that can be of any type.
If you would like to return None when the argument is null and Some otherwise, what you need is Option.bind, not Option.map. Option.bind takes a function that takes a value (extracted from a previous Option) and returns another Option. Something like this:
let maybeC = Option.ofObj cObj
let maybeB = maybeC |> Option.bind (c -> Option.ofObj c.B)
let maybeA = maybeB |> Option.bind (b -> Option.ofObj b.A)
let maybeP = maybeA |> Option.bind (a -> Option.ofObj a.P)
Or in one go:
let maybeP =
Option.ofObj cObj
|> Option.bind (c -> Option.ofObj c.B)
|> Option.bind (b -> Option.ofObj b.A)
|> Option.bind (a -> Option.ofObj a.P)
If you do this sort of thing very frequently, you can combine Option.bind and Option.ofObj calls and encode that as a separate function:
let maybeNull f = Option.bind (x -> Option.ofObj (f x))
let maybeP =
Option.ofObj cObj
|> maybeNull (c -> c.B)
|> maybeNull (b -> b.A)
|> maybeNull (a -> a.P)
However, if you find yourself buried in nulls like that, I would suggest that perhaps your domain design is not thought through very well. Nulls are not a good modeling tool, they should be avoided as much as possible. I encourage you to rethink your design.
The first argument to Option.map is a function 'T -> 'U. Its parameter is of type 'T, not 'T option. So, in your last lambda fun a -> a.P, a null argument denotes a null of type A, not a null of type A option.
Because the member P of type A just returns the string "Test," the call succeeds and returns even though the receiver is null. If you try to use the self identifier in the body of P, you will instead get a null reference exception.

How can I determine if a list of discriminated union types are of the same case?

Suppose I have a DU like so:
type DU = Number of int | Word of string
And suppose I create a list of them:
[Number(1); Word("abc"); Number(2)]
How can I write a function that would return true for a list of DUs where all the elements are the same case. For the above list it should return false.
The general approach I'd use here would be to map the union values into tags identifying the cases, and then check if the resulting set of tags has at most one element.
let allTheSameCase (tagger: 'a -> int) (coll: #seq<'a>) =
let cases =
coll
|> Seq.map tagger
|> Set.ofSeq
Set.count cases <= 1
For the tagger function, you can assign the tags by hand:
allTheSameCase (function Number _ -> 0 | Word _ -> 1) lst
or use reflection (note that you might need to set binding flags as necessary):
open Microsoft.FSharp.Reflection
let reflectionTagger (case: obj) =
let typ = case.GetType()
if FSharpType.IsUnion(typ)
then
let info, _ = FSharpValue.GetUnionFields(case, typ)
info.Tag
else -1 // or fail, depending what makes sense in the context.
In case you wanted to check that the elements of a list are of a specific union case, it's straightforward to provide a predicate function.
let isNumbers = List.forall (function Number _ -> true | _ -> false)
If you do not care which union case, as long as they are all the same, you need to spell them all out explicitly. Barring reflection magic to get a property not exposed inside F#, you also need to assign some value to each case. To avoid having to think up arbitrary values, we can employ an active pattern which maps to a different DU behind the scenes.
let (|IsNumber|IsWord|) = function
| Number _ -> IsNumber
| Word _ -> IsWord
let isSameCase src =
src |> Seq.groupBy (|IsNumber|IsWord|) |> Seq.length <= 1
I had the exact same use case recently and the solution can be done much simpler than complicated reflections or explicit pattern matching, GetType does all the magic:
let AreAllElementsOfTheSameType seq = // seq<'a> -> bool
if Seq.isEmpty seq then true else
let t = (Seq.head seq).GetType ()
seq |> Seq.forall (fun e -> (e.GetType ()) = t)

Generic type annotation in F#

I got the following error:
Error 2 Value restriction. The value 'gbmLikelihood' has been inferred to have generic type val gbmLikelihood : (float -> '_a -> float [] -> float) when '_a :> seq<float> Either make the arguments to 'gbmLikelihood' explicit or, if you do not intend for it to be generic, add a type annotation.
and this type is exactly what I want. What do I have to do to make it work, and why doesn't it just work without intervention?
EDIT:
The error comes from this file (its short, so I paste the whole lot):
module Likelihood
open System
let likelihood getDrift getVol dt data parameters =
let m = getDrift data parameters
let s = getVol data parameters
let N = float (Seq.length data)
let sqrt_dt = Math.Sqrt dt
let constant = -0.5*Math.Log(2.0*Math.PI*dt)*N
let normalizedResidue observation = (observation - (m - 0.5*s*s)*dt)/(s*sqrt_dt)
let residueSquared observation =
let r = normalizedResidue observation in r*r
let logStdDev = Math.Log s
constant - logStdDev*N - 0.5* (data |> Seq.sumBy residueSquared)
let gbmLikelihood = likelihood (fun data p -> Array.get p 0) (fun datac p -> Array.get p 1)
This error can happen when you declare a value that has a generic type. See for example this past SO question. In your case, the type suggests that you are trying to define a function, but the compiler does not see it as a syntactic function. This can happen if you perform some effects and then return function using the lambda syntax:
let wrong =
printfn "test"
(fun x -> x)
To avoid the problem, you need to write the function using the function syntax:
printfn "test"
let wrong x = x
EDIT: In your concrete example, the function gbmLikelihood is created as a result of a partial function application. To make it compile, you need to turn it into an explicit function:
let gbmLikelihood parameters =
likelihood (fun data p -> Array.get p 0) (fun datac p -> Array.get p 1) parameters
For more information why this is the case & how it works, see also this great article on value restriction in F#.
Instead of making the parameters of gbmLikelihood explicit you might also just add a generic type annotation to the function:
let gbmLikelihood<'a> =
likelihood (fun data p -> Array.get p 0) (fun datac p -> Array.get p 1)

Applying Seq.map using 2 sequences to a method which takes 2 parameters

I'm writing a quick DB perf test, and chose F# so I can get more practice.
I've created a method, measureSelectTimes, which has the signature Guid list * Guid list -> IDbCommand -> TimeSpan * TimeSpan.
Then, I call it:
let runTests () =
let sqlCeConn : IDbConnection = initSqlCe() :> IDbConnection
let sqlServerConn : IDbConnection = initSqlServer() :> IDbConnection
let dbsToTest = [ sqlCeConn; sqlServerConn ]
let cmds : seq<IDbCommand> = dbsToTest |> Seq.map initSchema
let ids : seq<Guid list * Guid list> = cmds |> Seq.map loadData
let input = Seq.zip ids cmds
let results = input |> Seq.map (fun i -> measureSelectTimes (fst i) (snd i))
// ...
I've annotated explicitly with types to clarify.
What I can't figure out is how to call measureSelectTimes without the lambda. I'd like to partially apply the ids to it like this: ids |> Seq.map measureSelectTimes but then I don't know what to do with the resulting partially applied functions to then map onto the cmds. What's the syntax for this?
You can use Seq.map2:
Seq.map2 measureSelectTimes ids cmds
Or
(ids, cmds) ||> Seq.map2 measureSelectTimes
Your measureSelectTimes function takes two arguments as separate arguments, but you instead need a function that takes them as a tuple. One option is to just change the function to take a tuple (if it is logical for the arguments to be tupled).
Alternative, you can write a cobinator that turns a function taking two arguments into a function taking tuple. This is usually called uncurry and it exists in some functional language:
let uncurry f (a, b) = f a b
Then you can write:
input |> Seq.map (uncurry measureSelectTimes)
This looks okay for a simple use like this, but I think that using combinators too much in F# is not a good idea as it makes code difficult to read for less experienced functional programmers. I would probably write something like this (because I find that more readable):
[ for (time1, time2) in input -> measureSelectTimes time1 time2 ]
One approach is to change the signature of measureSelectTimes to
(Guid list * Guid list) * IDbCommand -> TimeSpan * TimeSpan
Then you can change the map call to
let results = input |> Seq.map measureSelectTimes
// or
let results = Seq.map measureSelectTimes input

Resources