I have an array downloaded from a database where the property service_time is Nullable<DateTime>:
service_time: Nullable<DateTime>
In F#, how can I sort this array, placing all the elements with service_time = null firstmost in the new array?
Array.sortBy (fun t -> t.service_time)
gives: The type 'Nullable' does not support the 'comparison' constraint.
You can take advantage of the fact that default(DateTime) equals DateTime.MinValue and sort on service_time.GetValueOrDefault() like so:
Array.sortBy (fun t -> t.service_time.GetValueOrDefault())
Or, more explicitly:
Array.sortBy (fun t -> t.service_time.GetValueOrDefault(DateTime.MinValue))
If you wanted to put the nulls at the end of the array you could do:
Array.sortBy (fun t -> t.service_time.GetValueOrDefault(DateTime.MaxValue))
Demo fiddle here.
Related
I am trying to implement BST in F#. Since I am starting my journey with F# I wanted to ask for help.
I have simple a test;
[<Fact>]
let ``Data is retained`` () =
let treeData = create [4]
treeData |> data |> should equal 4
treeData |> left |> should equal None
treeData |> right |> should equal None
Tree type which uses discriminated unions
type Tree<'T> =
| Leaf
| Node of value: 'T * left: Tree<'T> * right: Tree<'T>
a recursive function which inserts data nodes into the tree
let rec insert newValue (targetTree: Tree<'T>) =
match targetTree with
| Leaf -> Node(newValue, Leaf, Leaf)
| Node (value, left, right) when newValue < value ->
let left' = insert newValue left
Node(value, left', right)
| Node (value, left, right) when newValue > value ->
let right' = insert newValue right
Node(value, left, right')
| _ -> targetTree
now I have problems with create function. I have this:
let create items =
List.fold insert Leaf items
and resulting error:
FS0001 Type mismatch. Expecting a
''a -> Tree<'a> -> 'a' but given a
''a -> Tree<'a> -> Tree<'a>' The types ''a' and 'Tree<'a>' cannot be unified.
The List.fold documentation shows its type signature as:
List.fold : ('State -> 'T -> 'State) -> 'State -> 'T list -> 'State
Let's unpack that. The first argument is a function of type 'State -> 'T -> 'State. That means it takes a state and an argument of type T, and returns a new state. Here, the state is your Tree type: starting at a basic Leaf, you're building up the tree step by step. Second argument to List.fold is the initial state (a Leaf in this case), and third argument is the list of items of type T to fold over.
Your second and third arguments are correct, but your first argument doesn't line up with the signature that List.fold is expecting. List.fold wants something of type 'State -> 'T -> 'State, which in your case would be Tree<'a> -> 'a -> Tree<'a>. That is, a function that takes the tree as its first parameter and a single item as its second parameter. But your insert function takes the parameters the other way around (the item as the first parameter, and the tree as the second parameter).
I'll pause here to note that your insert function is correct according to the style rules of idiomatic F#, and you should not change the order of its parameters. When writing functions that deal with collections, you always want to take the collection as the last parameter so that you can write something like tree |> insert 5. So I strongly suggest you don't change the order of the arguments your insert function takes.
So if you shouldn't change the order of arguments of your insert function, yet they're in the wrong order to use with List.fold, what do you do? Simple: you create an anonymous function with the arguments flipped around, so that you can use insert with List.fold:
let create items =
List.fold (fun tree item -> insert item tree) Leaf items
Now we'll go one step further and generalize this. It's actually pretty common in F# programming to find that your two-parameter function has the parameters the right way around for most things, but the wrong way around for one particular use case. To solve that problem, sometimes it's useful to create a general-purpose function called flip:
let flip f = fun a b -> f b a
Then you could just write your create function like this:
let create items =
List.fold (flip insert) Leaf items
Sometimes the use of flip can make code more confusing rather than less confusing, so I don't recommend using it all the time. (This is also why there isn't a flip function in the F# standard library: because it's not always the best solution. And because it's trivial to write yourself, its lack in the standard library is not a big deal). But sometimes using flip makes code simpler, and I think this is one of those cases.
P.S. The flip function could also have been written like this:
let flip f a b = f b a
This definition is identical to the let flip f = fun a b -> f b a definition I used in the main example. Do you know why?
I try to do some graphs in F#. As an input I have CSV file that has some values nullable (e.g. nullable int). I try to show chart with following code :
[for row in data.Rows -> row.A.Value, row.B.Value] |> Chart.Point
Where both A and B are nullable integers. I received following error
System.InvalidOperationException: Nullable object must have a value.
How I should handle nullable types. Should I write some Option type to handle it or there is some other good way how to solve it.
If you are using F# 4.0, then there is a built-in function Option.ofNullable. If no, then you can use the implementation in the other answer.
You can also use the same code to define an active pattern:
let (|Present|_|) (n:System.Nullable<_>) =
if n.HasValue then Some(n.Value)
else None
... this can be used inside a match construct and so you can write:
[ for row in data.Rows do
match row.A, row.B wih
| Present a, Present b -> yield a,b
| _ -> () ] |> Chart.Point
Where you are going wrong is: you are calling the Value property on something that might be null.
When you call Value you are effectively saying "It's okay, I have rigorously changed this value and it's definitely not null so it's perfectly safe to treat it as if it were a non-nullable value." Of course, in this case, that condition isn't met, hence the runtime exception.
In F#, you don't want to be working with Nullable<'T> types, you want to be working with Option<'T>, this is much safer and the compiler can check more effectively that you're not making a mistake.
You can convert from Nullable<'T> to Option<'T> for the list using
[for row in data.Rows -> Option.ofNullable (row.A), Option.ofNullable(row.B)]
Of course then you have to decide how you want to handle the None cases but it's much easier to do that once you've made your design explicitly tell you that you've got a value that may or may not be something.
I don't know what behaviour you want but, as an example, perhaps you want to only chart the cases where both values are valid?
You could zip two option values:
module Option =
let zip a b =
match (a,b) with
|Some sa, Some sb -> Some(sa, sb)
|_ -> None
You can then map back to plotable numbers, extracting the None cases using List.choose.
[for row in data.Rows -> Option.ofNullable (row.A), Option.ofNullable (row.B)]
|> List.choose (fun (a,b) -> Option.zip a b)
|> Chart.Point
Map the Nullable type to Option type and filter them out (with .filter or .choose) or transform the None's to a special value for missing values (e.g. 0, -1, NaN) depending on your data to make them working in the charting tool.
module Option =
let fromNullable (n: _ Nullable) =
if n.HasValue
then Some n.Value
else None
F#'s 'options' seem a nice way of using the type system to separate data that's known to be present from data which may or may not be present, and I like the way that the match expression enforces that all cases are considered:
match str with
| Some s -> functionTakingString(s)
| None -> "abc" // The compiler would helpfully complain if this line wasn't present
It's very useful that s (opposed to str) is a string rather than a string option.
However, when working with records that have optional fields...
type SomeRecord =
{
field1 : string
field2 : string option
}
...and those records are being filtered, a match expression feels unnecessary, because there's nothing sensible to do in the None case, but this...
let functionTakingSequenceOfRecords mySeq =
mySeq
|> Seq.filter (fun record -> record.field2.IsSome)
|> Seq.map (fun record -> functionTakingString field2) // Won't compile
... won't compile, because although records where field2 isn't populated have been filtered out, the type of field2 is still string option, not string.
I could define another record type, where field2 isn't optional, but that approach seems complicated, and may be unworkable with many optional fields.
I've defined an operator that raises an exception if an option is None...
let inline (|?!) (value : 'a option) (message : string) =
match value with
| Some x -> x
| None -> invalidOp message
...and have changed the previous code to this...
let functionTakingSequenceOfRecords mySeq =
mySeq
|> Seq.filter (fun record -> record.field2.IsSome)
|> Seq.map (fun record -> functionTakingString (record.field2 |?! "Should never happen")) // Now compiles
...but it doesn't seem ideal. I could use Unchecked.defaultof instead of raising an exception, but I'm not sure that's any better. The crux of it is that the None case isn't relevant after filtering.
Are there any better ways of handling this?
EDIT
The very interesting answers have brought record pattern matching to my attention, which I wasn't aware of, and Value, which I'd seen but misunderstood (I see that it throws a NullReferenceException if None). But I think my example may have been poor, as my more complex, real-life problem involves using more than one field from the record. I suspect I'm stuck with something like...
|> Seq.map (fun record -> functionTakingTwoStrings record.field1 record.field2.Value)
unless there's something else?
In this example, you could use:
let functionTakingSequenceOfRecords mySeq =
mySeq
|> Seq.choose (fun { field2 = v } -> v)
|> Seq.map functionTakingString
Seq.choose allows us to filter items based on optional results. Here we you pattern matching on records for more concise code.
I think the general idea is to manipulate option values using combinators, high-order functions until you would like to transform them into values of other types (e.g. using Seq.choose in this case). Using your |?! is discouraged because it is a partial operator (throwing exceptions in some cases). You can argue that it's safe to use in this particular case; but F# type system can't detect it and warn you about unsafe use in any case.
On a side note, I would recommend to take a look at Railway-Oriented Programming series at http://fsharpforfunandprofit.com/posts/recipe-part2/. The series show you type-safe and composable ways to handle errors where you can keep diagnostic information along.
UPDATE (upon your edit):
A revised version of your function is written as follows:
let functionTakingSequenceOfRecords mySeq =
mySeq
|> Seq.choose (fun { field1 = v1; field2 = v2 } ->
v2 |> Option.map (functionTakingString v1))
It demonstrates the general idea I mentioned where you manipulate option values using high-order functions (Option.map) and transform them at a final step (Seq.choose).
Since you have found the IsSome property, you might have seen the Value property as well.
let functionTakingSequenceOfRecords mySeq =
mySeq
|> Seq.filter (fun record -> record.field2.IsSome)
|> Seq.map (fun record -> functionTakingString record.field2.Value )
There's an alternative with pattern matching:
let functionTakingSequenceOfRecords' mySeq =
mySeq
|> Seq.choose (function
| { field2 = Some v } -> functionTakingString v |> Some
| _ -> None )
The problem as I interpreted is that you want to have the type system at all times reflecting the fact that those records in the collection actually contains a string in field2.
I mean, for sure you can use choose to filter out the records you don't care but still you will end up with a collection of records with an optional string and you know all of them would be Some string.
One alternative is to create a generic record like this:
type SomeRecord<'T> =
{
field1 : string
field2 : 'T
}
But then you can't use record expression to clone the record and change the generic type of the record at the same time. You will need to create the new record by hand, which will not be a major problem if the other fields are not so many and the structure is stable.
The other option is to wrap the record in a tuple with the desired value, here's an example:
let functionTakingSequenceOfRecords mySeq =
let getField2 record =
match record with
| {field2 = Some value} -> Some (value, record)
| _ -> None
mySeq
|> Seq.choose getField2
|> Seq.map (fun (f2, {field1 = f1}) -> functionTakingTwoStrings f1 f2)
So here you ignore the content of field2 and use instead the first value in the tuple.
Unless I misunderstood your problem and you don't care pattern matching again, or doing an incomplete matching with a warning or a #nowarn directive or using the .Value property of the option as shown in the other answers.
I have been doing a little reading on F# and decided to give it a try. I started with a somewhat involved example and I came up with and got lost immediately. I wonder if someone can share some thoughts on it.
I wanted to write a method called ComparisonStrategy<'T> that returns an instance of IEqualityComparer<'T>. It that takes in a variable length of ComparisonWhichAndHow<'T> instances. The type ComparisonWhichAndHow<'T> can either be:
One function of type ('T -> *), which is a method that selects a single field to compare
a 2-tuple of ('T -> 'U, IEqualityComparer<'U>) if you don't want the default Equals or GetHashCode to be used on 'U.
I have tried to draw this down on visual studio for a while now, but I can't even get the function declaration part right. I am somewhat positive I would be able to implement the method body if I can just get past this, but seems like I can't.
Edited:
This is the code I have tried so far.
I am trying to achieve the 2 following things.
Come up with a generic way of generating a equal method for each object.
Sometimes some business operations might require comparing some fields of 2 objects, and some fields of their children. Not a full comparison. I am trying to make writing those code more concise and simple
This is what I have so far:
module Failed =
open System.Collections.Generic
open System
type ComparsionOption<'T, 'U> =
| Compare of ('T -> 'U)
| CompareWith of ('T -> 'U) * IEqualityComparer<'U>
// TO USE: [<ParamArray>]
// TODO: this method returns a dummy for now
let CompareStrategy (opts : ComparsionOption<'T, _> array) =
EqualityComparer<'T>.Default
// How it's used
type Person(name : string, id : Guid) =
member this.Name = name
member this.ID = id
let fullCompare : EqualityComparer<Person> =
CompareStrategy [|Compare(fun (p : Person) -> p.Name);
CompareWith((fun (p : Person) -> p.ID), EqualityComparer<Guid>.Default)|] // error here
Looking at the problem from another perspective, it looks like you want to be able to construct objects that perform comparison in two different ways (which you specified) and then compose them.
Let's start by looking at the two ways to build an object that performs comparison. You can represent both by IEqualityComparer<'T>. The first one takes a function 'T -> Something and performs comparison on the result. You can define a function like this:
/// Creates a comparer for 'T values based on a predicate that
/// selects some value 'U from any 'T value (e.g. a field)
let standardComparer (f:'T -> 'U) =
{ new IEqualityComparer<'T> with
member x.Equals(a, b) =
(f a).Equals(b) // Call 'f' on the value & test equality of results
member x.GetHashCode(a) =
(f a).GetHashCode() } // Call 'f' and get hash code of the result
The function is 'T -> 'U using F# generics, so you can project fields of any type (the type just has to be comparable). The second primitive function also takes 'T -> 'U, but it also takes a comparer for 'U values instead of using the default:
/// Creates a comparer for 'T values based on a predicate & comparer
let equalityComparer (f:'T -> 'U) (comparer:IEqualityComparer<'U>) =
{ new IEqualityComparer<'T> with
member x.Equals(a, b) =
comparer.Equals(f a, f b) // Project values using 'f' and use 'comparer'
member x.GetHashCode(a) =
comparer.GetHashCode(f a) } // Similar - use 'f' and 'comparer'
Now you're saying that you'd like to take a sequence of values created in one of the two above ways to build a single comparison strategy. I'm not entirely sure what you mean by that. Do you want two objects to be equal when all the specified comparers report them as equal?
Assuming that is the case, you can write a function that combines two IEqualityComparer<'T> values and reports them as equal when both comparers report them as equal like this:
/// Creates a new IEqualityComparer that is based on two other comparers
/// Two objects are equal if they are equal using both comparers.
let combineComparers (comp1:IEqualityComparer<'T>) (comp2:IEqualityComparer<'T>) =
{ new IEqualityComparer<'T> with
member x.Equals(a, b) =
comp1.Equals(a, b) && comp2.Equals(a, b) // Combine results using &&
member x.GetHashCode(a) =
// Get hash code of a tuple composed by two hash codes
hash (comp1.GetHashCode(a), comp2.GetHashCode(a)) }
This is essenitally implementing all the functionality that you need. If you have some object Person, you can construct comparer like this:
// Create a list of primitive comparers that compare
// Name, Age and ID using special 'idComparer'
let comparers =
[ standardComparer (fun (p:Person) -> p.Name);
standardComparer (fun (p:Person) -> p.Age);
equalityComparer (fun (p:Person) -> p.ID) idComparer ]
// Create a single comparer that combines all of them...
let comparePerson = comparers |> Seq.reduce combineComparers
You could wrap this in a more object-oriented interface using overloaded methods etc., but I think that the above sample shows all the important components that you'll need in the solution.
BTW: In the example, I was using F# object expressions to implement all the functions.
I've noticed it seems to behave this way, but I don't want to rely on it if it's not intentional. Here's the code in question:
let bestValuesUnder max =
allValues
>> List.partition (fun value -> value < max)
>> function
| ([], bad) -> [List.min bad]
| (good, _) -> good // |> List.sortBy (fun value -> -value)
allValues is a function that returns an int list.
The spec does not say:
http://msdn.microsoft.com/en-us/library/ee353782(VS.100).aspx
but the current implementation in FSharp.Core does preserve order (it uses mutation under the hood to create the resulting lists in order, as it walks the original; this is efficient). I'll ask to see if we intend to promote this to the spec, as it seems like a useful guarantee.