Nullable anonymous record - f#

Based on a condition, i want to assign either an anonymous record or null to a variable.
For example
let cryptoParameters =
match status with
| Some cryptoParameters ->
{| SecretSalt = cryptoParameters.SecretSalt
PublicIdentityKey = cryptoParameters.PublicIdentityKey
PrivateIdentityKey = cryptoParameters.PrivateIdentityKey |}
| _ -> null
I keep getting the following error:
error FS0043: The type '{| PrivateIdentityKey: string; SecretSalt: string; PublicIdentityKey: string |}' does not have 'null' as a proper value

You can get null values by using Unchecked.defaultof. In the case of an anonymous type. You must provide the whole anonymous definition as an pamarameter like:
let x = Unchecked.defaultof<{|Name:string; Age:int|}>
in your case. The compiler can infer the type, and you can use underscore instead.
let isEven x = x % 2 = 0
let person =
match isEven 3 with
| true -> {Name="David"; Age=100}
| false -> Unchecked.defaultof<_>
But maybe you want to use the Option type instead of using null. That's the way how F# handles null. Because null is usally prohibited by F#.
If you have a problem because Option is a reference type, and it causes some kind of performance problems, then maybe you want to use the ValueOption type instead.
See additionally information on Option like:
Microsoft - Null Values in F#
Microsoft - Options
Microsoft - Value Options
F# for Fun and Profit - The Option Type

Related

How does one call bool.TryParse in F#

I need to call bool.TryParse in F# and I'm having a little difficulty with the compiler / Ionide.
Ex.
let value = true
let parsable = bool.TryParse("True", &value)
There error I'm seeing in Ionide for VSCode looks like the following.
val value : bool Full name:
value
Assembly: example3
The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In'F#
Compiler(1)
This is the first example that I've used call by ref keywords and syntax in F# so I'm not sure what I'm doing wrong and the byrefs documentation doesn't seem to be of much help on understanding this particular scenario.
It turns out that the main thing I was missing in my example was that value wasn't mutable as it would need to be when called in this context.
Working example:
let mutable value = true
let parsable = bool.TryParse("True", &value)
This solution came to me after reading a slightly related GitHub issue related to Span<T> and then also playing around in dotnet fsi which at least gave me the following clue.
let parsable = bool.TryParse("True", &value);;
-------------------------------------^^^^^^
stdin(34,38): error FS3230: A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'
As it turns out however F# also seems to have sntaxtic sugar around the Try-Parse pattern which I began to recall after playing around with this example further. This reduced into the below alternative solution to calling bool.TryParse.
let value = true
let (parsable, _) = bool.TryParse "True"
Alternatively without having to bind parsable and to specify the default value within a single expression the following example may be more elegant.
let value = match bool.TryParse "True" with
| true, value -> value
| false, _ -> true
Perhaps there are pros and cons to the different ways of calling bool.TryParse and other Try-Parse methods but the important thing is that I found some solutions that work and get me past the initial stumbling blocks with regard to lack of F# documentation on the subject.
As you have already discovered, the error can be fixed by making the 'value' a mutable variable.
Saying that, the last solution solution you shared (using pattern matching) looks the nicest and safest.
If you happen to do many of these parsing operations, I would suggest extracting some utility functions. That will avoid having to correctly pattern match on (true, value) rather than (false, value) by mistake.
Sample code:
open System
module Option =
let ofTry<'a> (res:(bool*'a)) : 'a option =
match res with
| true, res -> Some res
| false, _ -> None
module Result =
let ofTry<'a,'b> (err:'b) (res:(bool*'a)) : Result<'a, 'b> =
res
|> csharpToOption
|> Option.toResult err
module Samples =
let withPatternMatch =
match Int32.TryParse "5" with
| true, value -> value |> Some
| false, _ -> None
let withOptionHelper = Int32.TryParse "5" |> Option.ofTry
let withResultHelper = Int32.TryParse "5" |> Result.ofTry "Not a number"

How do I check whether a variable is an integer in F#?

I'm new in F#.
How do I check whether a variable is an integer or another type.
Thanks.
One way is listed by #ildjarn in the comments:
let isInt x = box x :? int
An idiomatic way would be to use pattern matching. First, define a discriminated union which defines the possible options:
type Test =
| IsAnInteger of int
| IsADouble of double
| NotANumber of Object
then use a match statement to determine which option you got. Note that when you initially create the value you wish to use with a match statement, you need to put it into the discriminated union type.
let GetValue x =
match x with
| IsAnInteger(a) -> a
| IsADouble(b) -> (int)b
| NotAnInteger(_) -> 0
Since you're probably going to use your test to determine control flow, you might as well do it idiomatically. This can also prevent you from missing cases since match statements give you warnings if you don't handle all possible cases.
>GetValue (NotAnInteger("test"));;
val it : int = 0
>GetValue (IsADouble(3.3))
val it : int = 3
>GetValue (IsAnInteger(5))
val it : int = 5
Considering that you tagged this question "c#-to-f#" I'm assuming you're coming to F# from a C# background. Therefore I think you may be a bit confused by the type inference since you're probably used to explicitly typing variables.
You can explicitly declare the type of a value if you need to.
let x:int = 3
But it's usually easier and better to let the type inference do this work for you. You'll note that I said value--the declaration above is not a variable because you cannot do a destructive assignment to it. If you want a variable then do this:
let mutable x:int = 3
You can then assign a new value to x via this construct
x <- 5
But, as a rule, you'll want to avoid mutable values.

value restriction case in F#

I am puzzled as to why the 3rd function would not work :
let generate1 = id
let generate2 = let a = 1
id
let generate3 = printfn "hi"
id
while the first 2 are fine, the last one spits out
error FS0030: Value restriction. The value 'generate3' has been inferred to have generic type
val generate3 : ('_a -> '_a)
Either make the arguments to 'generate3' explicit or, if you do not intend for it to be generic, add a type annotation.
I won't attempt to explain value restriction, but I will attempt to sort out the semantic differences between these three values.
generate1 is just an alias for id, so we're good there.
generate3 does some computations before returning id, hitting value restriction.
Then why doesn't generate2 hit value restriction like generate3? Because the compiler can see that let x = 1 in id is semantically equivalent to just id: 1 is a constant expression and x not used in the body of the let ... in ... expression, so the compiler can and does throw them away. On-the-other-hand, if you replace 1 with a potential side-effect like sin 2.3 (sin is pure, but the compiler can't prove it), then the compiler can't safely reduce the expression, thus hitting value restriction as with generate3.

F# - weird behavior when pattern matching discriminated unions

I've been writing some F# now for about 6 months and I've come across some behavior that I can't explain. I have some boiled down code below. (value names have been changed to protect the innocent!)
I have a hierarchy defined using record types rec1 and rec2, and also a dicriminated union type with possible values CaseA and CaseB. I'm calling a function ('mynewfunc') that takes a du_rec option type. Internally this function defines a recursive function that processes the hierarchy .
I'm kicking off the processing by passing the None option value to represent the root of the hierarchy (In reality, this function is deserializing the hierarchy from a file).
When I run the code below I hit the "failwith "invalid parent"" line of code. I can not understand why this is, because the None value that is passed down should match the outer pattern matching's None case.
The code works if I delete either of the sets of comments. This is not a showstopper for me - I just feel a bit uncomfortable not knowing why this is happening (I thought I was understanding f#)
Thanks in advance for any replies
James
type rec2 =
{
name : string
child : rec1 option
}
and rec1 =
{
name : string ;
child : rec2 option
}
and du_rec =
| Case1 of rec1
| Case2 of rec2
let mynewfunc (arg:du_rec option) =
let rec funca (parent:du_rec option) =
match parent with
| Some(node) ->
match node with
| Case2(nd) ->
printfn "hello"
(* | Case1(nd) ->
printfn "bye bye" *)
| _ ->
failwith "invalid parent"
| None ->
// printfn "case3"
()
funcb( None )
and funcb (parent: du_rec option) =
printfn "this made no difference"
let node = funca(arg)
()
let rootAnnot = mynewfunc(None)
Based on the comments, this is just a bad experience in the debugger (where the highlighting suggests that the control flow is going places it is not); the code does what you expect.
(There are a number of places where the F# compiler could improve its sequence-points generated into the pdbs, to improve the debugging experience; I think we'll be looking at this in a future release.)

Best way to determine variable type and treat each one differently in F#

I have a function that will create a select where clause, but right now everything has to be a string.
I would like to look at the variable passed in and determine what type it is and then treat it properly.
For example, numeric values don't have single quotes around them, option type will either be null or have some value and boolean will actually be zero or one.
member self.BuildSelectWhereQuery (oldUser:'a) = //'
let properties = List.zip oldUser.ToSqlValuesList sqlColumnList
let init = false, new StringBuilder()
let anyChange, (formatted:StringBuilder) =
properties |> Seq.fold (fun (anyChange, sb) (oldVal, name) ->
match(anyChange) with
| true -> true, sb.AppendFormat(" AND {0} = '{1}'", name, oldVal)
| _ -> true, sb.AppendFormat("{0} = '{1}'", name, oldVal)
) init
formatted.ToString()
Here is one entity:
type CityType() =
inherit BaseType()
let mutable name = ""
let mutable stateId = 0
member this.Name with get() = name and set restnameval=name <- restnameval
member this.StateId with get() = stateId and set stateidval=stateId <- stateidval
override this.ToSqlValuesList = [this.Name; this.StateId.ToString()]
So, if name was some other value besides a string, or stateId can be optional, then I have two changes to make:
How do I modify ToSqlValuesList to
have the variable so I can tell the
variable type?
How do I change my select function
to handle this?
I am thinking that I need a new function does the processing, but what is the best FP way to do this, rather than using something like typeof?
You can use a type test pattern in a match. Would this meet your needs?
let f (x : obj) =
match x with
| :? int -> "int"
| :? string -> "string"
| :? bool -> "bool"
| _ -> "who knows?"
I think that one clear functional approach would be to define a data type that represents the various (more complicated situations) that you need to handle. You mentioned that a value may be optional and that you need to distinguish numeric and textual values (for the encoding to SQL).
You could define a discriminated union (if there are other cases that you'd like to handle, the definition may be a bit more complicated):
type SqlValue =
| Missing
| Numeric of string
| Textual of string
Note that the Textual case also carries string, because I assume that the client who produces the value takes care of converting it to string - this is only information for your SQL query generator (so that it knows whether it needs to add quotes).
Your ToSqlValuesList member would return a list of values string & SqlValue, so for example, a sample product could be represented using the following list:
columns = [ "Name"; "Price"; "Description" ]
values = [ Textual("Tea"); Numeric(10); Missing ]
In the code that generates the SQL query, you'd use pattern matching to handle all the different cases (most importantly, encode string to avoid SQL injection in case the value is Textual :-)).
EDIT You'd need to implement the conversion from the specific data types to the SqlValue representation in every client. However, this can be simplified by writing a utility type (using the fact that members can be overloaded):
type SqlValue with
static member From(a:int) = Numeric(a.ToString())
static member From(a:int option) =
match a with None -> Missing | Some(n) -> SqlValue.From(n)
// ... similarly for other types
In the implementation of ToSqlValuesList, you would write SqlValue.From(description) and it would deal with the details autoamtically.
A more sophisticated approach would be to annotate public members of the types representing your data entities with .NET attributes and use Reflection to extract the values (and their types) at runtime. This is more advanced, but quite elegant (there is a nice exmaple of this technique in Don Syme's Expert F# book)

Resources