c# to f# conversion with interfaces and linq statements - f#

I'm trying to convert this c# method that uses interfaces and Linq to f#:
public static IEnumerable<ModelEngines> CurrentEngineBuilds(IEnumerable<CurrentModels> thisYearModels, DateTime startRunDate, DateTime endRunDate)
{
var engineOptions =
currentModelYear.SelectMany(c => c.Engines)
.Where(e => e.EngineProdStartDate >= startRunDate & e.EngineProdStopDate <= endRunDate);
return engineOptions;
}
In the method above, I'm returning a collection of engineOptions - type is IEnumerable. I'm filtering the collection so that the collection only has engineOptions with a certain production range from the current model year.
I have this rough, non-working, translation below:
let CurrentEngineBuilds : <IEnumerable<ModelEngines>> (thisYearModels : IEnumerable<CurrentModels>) (startRunDate : DateTime) (endRunDate : DateTime) =
query {
for engineOptions in currentModelYear.engineOptions do
where (engineOptions.EngineProdStartDate >= startRunDate and engineOptions.EngineProdEndDate >= endRunDate )
select (engineOptions)
}
engineOptions
This task has become more complicated than I had anticipated. I've gone through a few f# tutorials to get through the basics, but it seems anything to do with interfaces and/or linq is pretty difficult.
Some issues I have:
How the heck to you work with interfaces in f#?
Is there an f# equivilent of the SelectMany method?
Any tips on how to do this c# to f# conversion?

IEnumerable<'T> is named seq<'T> in F#. I don't see any reason to use LINQ query expressions in this case; the more idiomatic F# translation would use the Seq module:
let CurrentEngineBuilds thisYearModels startRunDate endRunDate =
thisYearModels
// v--- SelectMany
|> Seq.collect (fun c -> c.Engines)
// v--- Where
|> Seq.filter (fun e ->
e.EngineProdStartDate >= startRunDate && e.EngineProdStopDate <= endRunDate)
If the type of thisYearModels is not deduced automatically, you can annotate it in the function signature:
let CurrentEngineBuilds (thisYearModels:seq<CurrentModels>) startRunDate endRunDate = ...
or in the body:
let CurrentEngineBuilds thisYearModels startRunDate endRunDate =
(thisYearModels:seq<CurrentModels>)
|> Seq.collect (fun c -> c.Engines)
|> Seq.filter (fun e ->
e.EngineProdStartDate >= startRunDate && e.EngineProdStopDate <= endRunDate)
// or
let CurrentEngineBuilds thisYearModels startRunDate endRunDate =
thisYearModels
|> Seq.collect (fun (c:CurrentModels) -> c.Engines)
|> Seq.filter (fun e ->
e.EngineProdStartDate >= startRunDate && e.EngineProdStopDate <= endRunDate)

You can actually use LINQ in F# without any problems whatsoever. Here's an almost direct port of your original sample (I'm assuming that currentModelYear is a type and you meant thisYearModels)
open System.Linq
let currentEngineBuilds(thisYearModels:seq<CurrentModels>, startRunDate, endRunDate) =
let engineOptions =
thisYearModels
.SelectMany(fun e -> e.Engines)
.Where(fun e -> e.StartDate >= startRunDate && e.StopDate <= endRunDate)
engineOptions // return keyword not required
For the purposes of this post, you can think of seq<T> as a shorthand for IEnumerable<T>.
Having said that, I think that you'll find the Seq module a better fit for F# as it's designed to take advantage of F# language features such as Tuples, and can assist in the type inference process.

The |> or "pipe" operator is F#'s idiomatic way of applying a function to a value.
v |> f is the same as f v as pointed out earlier.
Monadic chaining, on the other hand, is quite another matter entirely. You're using monadic chaining in the query computation expression in the original post, and it is also idiomatic.
Hope that helps to keep those two (fairly complex) concepts apart in your understanding! :)

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

Strongly typed but user-extensible collection in F#?

I am designing a data-structure for interacting with a C# API from F#. Broadly speaking, it is a strongly-typed collection of components (ComponentCollection), where components may have different types.
A first-pass looks like this:
type Foo =
{
Foo : int
}
type Bar =
{
Bar : string
}
type ComponentCollection =
{
FooComponents : Map<Foo, Component<Foo>>
BarComponents : Map<Bar, Component<Bar>>
}
module ComponentCollection =
let addFoo foo comp xs =
{ xs with FooComponents = xs.FooComponents |> Map.add foo comp }
let addBar bar comp xs =
{ xs with BarComponents = xs.BarComponents |> Map.add bar comp }
let tryFindFoo foo xs =
xs.FooComponents |> Map.tryFind foo
let tryFindBar bar xs =
xs.BarComponents |> Map.tryFind bar
There are two problems with this design:
Repetition of boiler-plate code (e.g. addFoo, addBar, tryFindFoo, ...)
The type of components is not extensible without changing the type ComponentCollection, e.g. a user cannot add QuxComponents : Map<Qux, Component<Qux>> themselves
I can redesign things using interfaces, but this loses much of the type safety F# is famous for!
open System
type ComponentKey =
interface
inherit IComparable
end
type Foo =
{
Foo : int
}
with interface ComponentKey
type Bar =
{
Bar : string
}
with interface ComponentKey
type ComponentCollection =
{
Components : Map<ComponentKey, obj>
}
module ComponentCollection =
let addFoo (foo : Foo) (comp : Component<Foo>) xs =
{ xs with Components = xs.Components |> Map.add (foo :> ComponentKey) (comp :> obj) }
let addBar (bar : Bar) (comp : Component<Bar>) xs =
{ xs with Components = xs.Components |> Map.add (bar :> ComponentKey) (comp :> obj) }
let tryFindFoo (foo : Foo) xs =
xs.Components
|> Map.tryFind (foo :> ComponentKey)
|> Option.map (fun x -> x :?> Component<Foo>) // Big assumption!
let tryFindBar (bar : Bar) xs =
xs.Components
|> Map.tryFind (bar :> ComponentKey)
|> Option.map (fun x -> x :?> Component<Bar>) // Big assumption!
// User can easily add more in their own code
How can I design ComponentCollection achieving type-safety and extensibility?
There's a few layers to this question, so I'll try give an answer that addresses the essence of it without running too long.
What you're essentially trying to get here is a map that is heterogenous both with regard to the key and to the value types. This is not something F# type system is well suited to represent, as it requires support for existential types that F# doesn't have. Let's leave the key part for a moment and talk about values.
What you have done in your second approach with boxing the values is generally a reasonable solution to storing heterogenous values in a collection, and a trade-off that people would often make. You give up some type safety by boxing and casting, but if you restrict access to your Components map by making it private/internal, and ensure it's only accessed through the module functions, you can easily keep the invariant that the type of key matches the type of component.
So you can remove the boilerplate with something like this:
module ComponentCollection =
let add<'key when 'key :> ComponentKey> (key: 'key) (comp: Component<'key>) coll =
{ coll with Components =
coll.Components |> Map.add (key :> ComponentKey) (box comp) }
let tryFind<'key when 'key :> ComponentKey> (key: 'key) coll =
coll.Components
|> Map.tryFind (key :> ComponentKey)
|> Option.map (fun x -> x :?> Component<'key>)
There is a solution around this problem that would work within the F# type system without resorting to casting or reflection, and it involves emulating existential types using a set of wrappers. This approach has been covered in other questions as well as this blog post in great detail. It is however a bulky encoding that would be hard for me to justify in a small project.
There is a separate problem with your proposed solution however - the fact you're using heterogenous keys for the map. As it currently stands, your approach (a marker interface that is essentially an alias for IComparable) will work fine as long as all the keys are of the same type, but the moment you try to add a key of a different type, the operation will fail in the Map internals - as the default comparison implementation would throw an exception when the compared values are of different runtime types.
To avoid that, you should either wrap your keys in a type that would have a custom implementation of comparisons that would circumvent that, or you should consider defining a common key type that you could use with all the component types you expect.

Dapper generic typehandler for F# Union types

I'm using union types similar to enums on my dapper objects:
type Confidence =
| Low
| Medium
| High
type Goal = {
Confidence: Confidence
...
}
I've created a custom type handler in order to make it work:
type UnionHandler<'T>() =
inherit SqlMapper.TypeHandler<'T>()
override __.SetValue(param, value) =
param.Value <- value.ToString()
()
override x.Parse(value: obj) =
Union.parse <| string value
let registerTypeHandlers() =
SqlMapper.AddTypeHandler (UnionHandler<Confidence>())
This works fine, but it would be even nicer if I didn't have to register a new one for each new union type.
Is it possible to make the type handler generic in such a way that it can handle all union types with only one registration?
This can be done with Reflection:
let internal addUnionTypeHandlers() =
let assembly = Assembly.GetExecutingAssembly()
let unionHandlerType =
assembly.GetTypes()
|> Seq.filter(fun t -> t.Name.Contains("UnionHandler") && t.IsGenericTypeDefinition)
|> Seq.head
assembly.GetTypes()
|> Seq.filter(fun t -> not t.IsGenericType && FSharpType.IsUnion(t, BindingFlags.Default))
|> Seq.iter(fun t ->
let ctor = unionHandlerType
.MakeGenericType(t)
.GetConstructor(Array.empty)
.Invoke(Array.empty)
(typeof<SqlMapper>.GetMethods()
|> Seq.filter(fun methodInfo ->
if methodInfo.Name = "AddTypeHandler" && methodInfo.IsGenericMethodDefinition then
let gp = methodInfo.GetParameters()
not <| isNull gp && gp.Length = 1 && gp.[0].ParameterType.Name.Contains("TypeHandler")
else false)
|> Seq.head)
.MakeGenericMethod(t)
.Invoke(null, [| ctor |]) |> ignore
)
Note:
It would have been much simpler if Dapper have had the signature of AddTypeHandler in a form ITypeHandler -> unit. But it accepts TypeHandler and in addition has overloaded version. So we need GMD for method AddTypeHandler and instantiate it with method MakeGenericMethod and then call this method with parameter which we obtains from GetConstructor ... Invoke
Playing further with reflection you can decide to mark some discriminated unions with some attribute to ignore adding the mapping. You can extend code to analyse if type has attribute. Also you can do manipulations on module basis I assume using FSharpType.IsModule

IQueryable lambda style in F#

Is it possible to use lambda-style querying of IQueryable objects in F#, instead of query expressions? Something like:
type schema = SqlDataConnection<"Data Source=(local);Initial Catalog=MyDatabase;Integrated Security=true;">
let db = schema.GetDataContext()
let q = db.MyTable |> Seq.filter (fun r -> r.id < 100) |> Seq.take 10
let result = q |> List.ofSeq
When I profile this it is doing select * from MyTable so I assume the filter and take are being executed on IEnumerables not IQueryables?
Or is the only way to fix this to use query {} without lambdas?
The reason is that Seq.toList calls the data struncture GetEnumerator() and there is something like this inside the type (pseudo, not the actual source):
type SqlDataConnection<...>(...) =
interface seq<'T> with
member __.GetEnumerator() = executeSQL()
If you want to operate with IQueryable instead of IEnumerable, there is the query-syntax in F#:
query {
for r in db.MyTable do
where (r.id < 100)
take 10
} |> Seq.toList
More details:
https://learn.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/query-expressions

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

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 )

Resources