F# computation expressions: Can one be used to simplify this code? - f#

I have recently started using computation expressions to simplify my code. So far the only useful one for me is the MaybeBuilder, defined thusly:
type internal MaybeBuilder() =
member this.Bind(x, f) =
match x with
| None -> None
| Some a -> f a
member this.Return(x) =
Some x
member this.ReturnFrom(x) = x
But I would like to explore other uses. One possibility is in the situation I am currently facing. I have some data supplied by a vendor that defines a symmetric matrix. To save space, only a triangular portion of the matrix is given, as the other side is just the transpose. So if I see a line in the csv as
abc, def, 123
this means that the value for row abc and column def is 123. But I will not see a line such as
def, abc, 123
because this information has already been given due to the symmetrical nature of the matrix.
I have loaded all this data in a Map<string,Map<string,float>> and I have a function that gets me the value for any entry that looks like this:
let myLookupFunction (m:Map<string,Map<string,float>>) s1 s2 =
let try1 =
match m.TryFind s1 with
|Some subMap -> subMap.TryFind s2
|_ -> None
match try1 with
|Some f -> f
|_ ->
let try2 =
match m.TryFind s2 with
|Some subMap -> subMap.TryFind s1
|_ -> None
match try2 with
|Some f -> f
|_ -> failwith (sprintf "Unable to locate a value between %s and %s" s1 s2)
Now that I know about computation expressions, I suspect that the match statements can be hidden.
I can clean it up slightly using the MaybeBuilder like so
let myFunction2 (m:Map<string,Map<string,float>>) s1 s2 =
let maybe = new MaybeBuilder()
let try1 = maybe{
let! subMap = m.TryFind s1
return! subMap.TryFind s2
}
match try1 with
|Some f -> f
|_ ->
let try2 = maybe{
let! subMap = m.TryFind s2
return! subMap.TryFind s1
}
match try2 with
|Some f -> f
|_ -> failwith (sprintf "Unable to locate a value between %s and %s" s1 s2)
Doing so, I have gone from 4 match statements to 2. Is there a (not contrived) way of cleaning this up even further by using computation expressions?

First of all, creating a new MaybeBuilder every time you need it is kinda wasteful. You should do that once, preferably right next to the definition of MaybeBuilder itself, and then just use the same instance everywhere. This is how most computation builders work.
Second: you can cut down on the amount of clutter if you just define the "try" logic as a function and reuse it:
let myFunction2 (m:Map<string,Map<string,float>>) s1 s2 =
let try' (x1, x2) = maybe{
let! subMap = m.TryFind x1
return! subMap.TryFind x2
}
match try' (s1, s2) with
|Some f -> f
|_ ->
match try' (s2, s1) with
|Some f -> f
|_ -> failwith (sprintf "Unable to locate a value between %s and %s" s1 s2)
Third, notice the pattern you're using: try this, if not try that, if not try another, etc. Patterns can be abstracted as functions (that's the whole gig!), so let's do that:
let orElse m f = match m with
| Some x -> Some x
| None -> f()
let myFunction2 (m:Map<string,Map<string,float>>) s1 s2 =
let try' (x1, x2) = maybe{
let! subMap = m.TryFind x1
return! subMap.TryFind x2
}
let result =
try' (s1, s2)
|> orElse (fun() -> try' (s2, s1))
match result with
|Some f -> f
|_ -> failwith (sprintf "Unable to locate a value between %s and %s" s1 s2)
And finally, I think you're going about it the wrong way. What you really seem to be after is a dictionary with two-part symmetric key. So why not just do that?
module MyMatrix =
type MyKey = private MyKey of string * string
type MyMatrix = Map<MyKey, float>
let mkMyKey s1 s2 = if s1 < s2 then MyKey (s1, s2) else MyKey (s2, s1)
let myFunction2 (m:MyMatrix.MyMatrix) s1 s2 =
match m.TryFind (MyMatrix.mkMyKey s1 s2) with
| Some f -> f
| None -> failwith (sprintf "Unable to locate a value between %s and %s" s1 s2)
Here, MyKey is a type that encapsulates a pair of strings, but guarantees that those strings are "in order" - i.e. the first one is lexicographically "less" than the second one. To guarantee this, I made the constructor of the type private, and instead exposed a function mkMyKey that properly constructs the key (sometimes referred to as "smart constructor").
Now you can freely use MyKey to both construct and lookup the map. If you put in (a, b, 42), you will get out both (a, b, 42) and (b, a, 42).
Some aside: the general mistake I see in your code is failure to use abstraction. You don't have to handle every piece of the data at the lowest level. The language allows you to define higher-level concepts and then program in terms of them. Use that ability.

I understand this might be just a simplification for the purpose of asking the question here - but what do you actually want to do when none of the keys is found and how often do you expect that the first lookup will fails?
There are good reasons to avoid exceptions in F# - they are slower (I don't know how much exactly and it probably depends on your use case) and they are supposed to be used in "exceptional circumstances", but the language does have a nice support for them.
Using exceptions, you can write it as a pretty readable three-liner:
let myLookupFunction (m:Map<string,Map<string,float>>) s1 s2 =
try m.[s1].[s2] with _ ->
try m.[s2].[s1] with _ ->
failwith (sprintf "Unable to locate a value between %s and %s" s1 s2)
That said, I completely agree with Fyodor that it would make a lot of sense to define your own data structure for keeping the data rather than using a map of maps (with possibly switched keys).

Related

Dynamic functions in F#

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]

Working with missing values in Deedle Time Series in F# (3)

This is another follow-up to Working with missing values in Deedle Time Series in F# (2)
I have written this function to map2 series, returning a missing value when either input is missing.
let map2series (f:'T1->'T2->'R)(series1:Series<'K,'T1 opt>)(series2:Series<'K,'T2 opt>):Series<'K,'R opt>=
let S = series1.Zip(series2,JoinKind.Outer) //Series<'K,('T1 opt opt * 'T2 opt opt)>
S |> Series.mapValues (fun (a,b) -> match (a,b) with
| (OptionalValue.Present(a'), OptionalValue.Present(b')) -> OptionalValue.map2 f a' b'
| _ -> OptionalValue.Missing)
since Series<'K,'T opt> appear naturally in Deedle after using .Zip or .Join methods.
However, as seen previously, Series<'K,'V> already supports missing values, so I'd like to rewrite the function above that basically would do the same except that it takes Series<'K,'V> as inputs
let map2series1 (f:'T1->'T2->'R)(series1:Series<'K,'T1>)(series2:Series<'K,'T2>):Series<'K,'R>=
let S = series1.Zip(series2,JoinKind.Outer) //Series<'K,('T1 opt * 'T2 opt)>
S |> Series.mapValues (fun (a,b) -> match (a,b) with
| (OptionalValue.Present(a'), OptionalValue.Present(b')) -> f a' b'
| _ -> None)
However this doesn't work, i don't have the right syntax in the second union case when one value is missing...
basically instead of the last None, i need to assign a value which corresponds to <missing> but i can't find it.
I also looked at something like
Option.bind OptionalValue.asOption OptionalValue.Missing but cannot find the right expression
You can do it this way:
let map2 f =
function
| OptionalValue.Present(a'), OptionalValue.Present(b') -> Some (f a' b')
| _ -> None
let map2series f series1 series2 =
series2
|> Series.zip series1
|> Series.mapAll(fun _ -> Option.bind(map2 f))

F# Monad multiple parameters

I am trying to wrap my head around monads and how to use them in real world examples. The first "task" i set myself is to write an "Exception Monad" which of course (at this point) is nothing more than the "Either monad" twisted to suit my purpose.
My code looks like this:
type MException<'a> =
| Success of 'a
| Failure of string
with
static member returnM a =
Success a
static member bind f =
fun e ->
match e with
| Success a -> f a
| Failure m -> Failure m
static member map f =
fun e ->
match e with
| Success a -> Success (f a)
| Failure m -> Failure m
// Create a little test case to test my code
let divide (n, m) =
match m with
| 0 -> Failure "Cannot divide by zero"
| _ -> Success ((float n) / (float m))
let round (f:float) =
Success ( System.Math.Round(f, 3) )
let toString (f:float) =
sprintf "%f" f
let divideRoundAndPrintNumber =
divide
>> MException<_>.bind round
>> MException<_>.map toString
// write the result
let result = divideRoundAndPrintNumber (11, 3)
match result with
| Success r -> printf "%s\n" r
| Failure m -> printf "%s\n" m
My question is the following: the divide function now takes a tuple. What can or should I do to make the bind and map functions behave correctly for functions with multiple parameters?
EDIT 30-12-2015:
Both the answers and comments of #Mark Seemann helped find the answer to the problem. #Mikhail provided the implementation of the solution. Currying is the right way of solving the problem. Computation Expressions are not a solution but a syntax abstraction which does work but gets complicated once you add async and other patterns to the problem. "Simple" composition seems like the easiest and "trueest" solution.
Change divideRoundAndPrintNumber to be a function instead of a value
let divide n m =
match m with
| 0 -> Failure "Cannot divide by zero"
| _ -> Success ((float n) / (float m))
let divideRoundAndPrintNumber n =
divide n
>> MException<_>.bind round
>> MException<_>.map toString
Unfortunately I do not know enough about F# to understand your code completely. For example I do not understand the >> operator and the MException<_> expression. But I can give you an alternative solution for your problem. It utilzies a F# feature called "Computation Expressions". It enables you to do "Monadic" magic in a nice F#-like way:
type MException<'a> =
| Success of 'a
| Failure of string
type ExceptionBuilder() =
member this.Bind (m, f) =
match m with
| Success a -> f a
| Failure m -> Failure m
member this.Return (x) =
Success (x)
let ex = new ExceptionBuilder()
let divide n m =
if m = 0 then Failure "Cannot divide by zero"
else Success ((float n)/(float m))
let round (f : float) =
Success (System.Math.Round(f, 3))
let divideRoundAndPrintNumber a b =
ex {
let! c = divide a b
let! d = round c
printf "result of divideRoundAndPrintNumber: %f\n" d
return d
}
let result = divideRoundAndPrintNumber 11 0
match result with
| Success r -> printf "%f\n" r
| Failure m -> printf "%s\n" m
Apologies when my answer does not match your question completely but I hope it helps.
Here you can find an excellent blog post series about this topic:
http://fsharpforfunandprofit.com/posts/computation-expressions-intro/
I also found this article very enlightening:
http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
Monads have a fairly strict required structure, they must have:
Return: 'a -> m<'a>
and
Bind: m<'a> -> ('a -> m<'b>) -> m<'b>
Your divide function has the signature int*int -> MException<float>, i.e. it does indeed have the required 'a -> m<'b> form to be used with bind. When used with bind, it would act on something of type MException<int*int> and produce an MException<float>.
If divide is instead of type int -> int -> MException<float> (i.e. 'a -> 'b -> m<'c>'), we can't use it with bind directly. What we can do is unwrap the tuple and then supply the arguments one by one to create a lambda that does have the right form.
Let's add an extra Return so that we can see more clearly some different approaches for handling functions within these constraints:
let divideTupled (n, m) =
match m with
| 0 -> Failure "Cannot divide by zero"
| _ -> Success ((float n) / (float m))
let divideRoundAndPrintNumber n m =
MException<_>.Return (n,m)
|> MException<_>.Bind divideTupled
|> MException<_>.Bind round
|> MException<_>.Map toString
or
let divideCurried n m =
match m with
| 0 -> Failure "Cannot divide by zero"
| _ -> Success ((float n) / (float m))
let divideRoundAndPrintNumber n m =
MException<_>.Return (n,m)
|> MException<_>.Bind (fun (n,m) -> divideCurried n m)
|> MException<_>.Bind round
|> MException<_>.Map toString
Computation expressions, as mentioned by Olaf, provide some nice syntactic sugar for working with monads in F#.
Why not define divide like you normally would?
let divide n m =
match m with
| 0 -> Failure "Cannot divide by zero"
| _ -> Success ((float n) / (float m))
You could then define divideRoundAndPrintNumber like this, likewise in curried form:
let divideRoundAndPrintNumber n m =
divide n m
|> MException<_>.bind round
|> MException<_>.map toString
FSI ad-hoc tests:
> let result = divideRoundAndPrintNumber 11 3;;
val result : MException<string> = Success "3.667000"
> let result = divideRoundAndPrintNumber 11 0;;
val result : MException<string> = Failure "Cannot divide by zero"

fold or choose till None?

Is there already a way to do something like a chooseTill or a foldTill, where it will process until a None option is received? Really, any of the higher order functions with a "till" option. Granted, it makes no sense for stuff like map, but I find I need this kind of thing pretty often and I wanted to make sure I wasn't reinventing the wheel.
In general, it'd be pretty easy to write something like this, but I'm curious if there is already a way to do this, or if this exists in some known library?
let chooseTill predicate (sequence:seq<'a>) =
seq {
let finished = ref false
for elem in sequence do
if not !finished then
match predicate elem with
| Some(x) -> yield x
| None -> finished := true
}
let foldTill predicate seed list =
let rec foldTill' acc = function
| [] -> acc
| (h::t) -> match predicate acc h with
| Some(x) -> foldTill' x t
| None -> acc
foldTill' seed list
let (++) a b = a.ToString() + b.ToString()
let abcdef = foldTill (fun acc v ->
if Char.IsWhiteSpace v then None
else Some(acc ++ v)) "" ("abcdef ghi" |> Seq.toList)
// result is "abcdef"
I think you can get that easily by combining Seq.scan and Seq.takeWhile:
open System
"abcdef ghi"
|> Seq.scan (fun (_, state) c -> c, (string c) + state) ('x', "")
|> Seq.takeWhile (fst >> Char.IsWhiteSpace >> not)
|> Seq.last |> snd
The idea is that Seq.scan is doing something like Seq.fold, but instead of waiting for the final result, it yields the intermediate states as it goes. You can then keep taking the intermediate states until you reach the end. In the above example, the state is the current character and the concatenated string (so that we can check if the character was whitespace).
A more general version based on a function that returns option could look like this:
let foldWhile f initial input =
// Generate sequence of all intermediate states
input |> Seq.scan (fun stateOpt inp ->
// If the current state is not 'None', then calculate a new one
// if 'f' returns 'None' then the overall result will be 'None'
stateOpt |> Option.bind (fun state -> f state inp)) (Some initial)
// Take only 'Some' states and get the last one
|> Seq.takeWhile Option.isSome
|> Seq.last |> Option.get

How to find the value in a list at which a maximum value of a function occurs

I want to find not just the maximum value of a function applied to a list (for which I would just use List.maxBy) but also the value in the list this occurred at. This feels like a fairly common operation and given the richness of the F# libraries in general I wouldn't be at all surprised to discover it was actually already available but I cannot seem to find it if it is!
To illustrate with an example, I want to be able to map a list domain and a function f
let domain = [0 .. 5]
let f x = -x * (x - 2)
to (1, 1) (since the function applied to an other element of the list is less than 1).
I first tried this:
let findMaximum domain f =
let candidates = [ for x in domain do
yield x, f x ]
let rec findMaximumHelper domain f currentMax =
match domain with
| [] -> currentMax
| head::tail ->
let cand = f head
match currentMax with
| None ->
let newMax = Some(head, cand)
findMaximumHelper tail f newMax
| Some(maxAt, possMax) ->
let newMax =
if cand > possMax then Some(head, cand)
else Some(maxAt, possMax)
findMaximumHelper tail f newMax
findMaximumHelper domain f None
let answer = findMaximum domain f
at which point I realised this is very close to a fold operation, and put together
let findMaximum2 domain f =
let findMaximumHelper f acc x =
let cand = f x
match acc with
| None -> Some(x, cand)
| Some(maxAt, possMax) ->
if cand > possMax then Some(x, cand)
else Some(maxAt, possMax)
List.fold (findMaximumHelper f) None domain
let answer2 = findMaximum2 domain f
instead.
My question is, are these idiomatic F# ways of solving this problem, or indeed, is there a better way of solving this?
Indeed, the F# library provides all the necessary higher order functions to express this succinctly:
domain
|> Seq.map (fun x -> x, f x)
|> Seq.maxBy snd
Note: updated to use Seq.map and Seq.maxBy instead of List.map and List.maxBy to address #ildjarn's concern about creating an unnecessary intermediate list.
An alternative to Stephen's answer, that avoids creating a second List, with the tradeoff of executing f one extra time:
domain
|> List.maxBy f
|> fun x -> x, f x

Resources