How to use "If not null Else" to set value? - f#

In VB.NET you can write this
Dim mammal as IAnimal = new Mammal
Dim bird as IAnimal = new Bird
' If mammal is not Nothing, animal is mammal, else it's bird
Dim animal IAnimal = If(mammal, bird) ' animal is mammal
Dim mammal as IAnimal
Dim bird as IAnimal = new Bird
' animal is now Bird
Dim animal IAnimal = If(mammal, bird)
And in C#
IAnimal mammal = new Mammal()
IAnimal bird = new Bird()
// If mammal is not null, animal is mammal, else it's bird
IAnimal animal = mammal ?? bird; // animal is mammal
IAnimal mammal;
IAnimal bird = new Bird()
// animal is now bird
IAnimal animal = mammal ?? bird;
But how to do it in F#? Is there any short syntax like in VB.NET and C#?
I came up with this as a replacement until I find out if/how it's done.
let IfNotNullElse (v1, v2) =
if v1 <> null then
v1
else
v2

In idiomatic self-contained F# you don't have the idea that anything could be null at any time so it's more common to use the Option type and supply default values like this:
Some 1 |> Option.defaultValue 2 // 1
None |> Option.defaultValue 2 // 2
However if you are working with .NET nullable references then you could define your own null coalescing operator. Unfortunately ?? is not allowed as an operator name:
let (|?) a b = if isNull a then b else a
null |? null |? "a" // "a"
"a" |? null // "a"
(null:string) |? null // null
But beware that there is no lazy evaluation here. The expressions to the right of |? are always evaluated in full.

Related

How can I Clone a Partial class in F# and change one property

I have a partial class in F# - actually referenced to a C# project ( and it was generated in the C# project from a SQL database )
I can easily extract the data from SQL Server - but I want to change one of the properties in the partial class. I can't easily see a way to copy the class and change one property/ member of the class at the same time.
Note: Ideally - I don't want to change the class structure because it's auto-generated from a different project.
If it was a record - I would use
let myRecord3 = { myRecord2 with Y = 100; Z = 2 }
but it's not and I can't quite get my head around who I would do this. thanks for your time.
If I understand your request, you have an object and you want to create a second object that has some new values but is otherwise a copy of the original. I think you can do this by creating a copy constructor and then specifying new values for whatever properties you want when you call it. Here's an example:
type Person() =
// copy constructor
new (person : Person) as this =
Person() then
this.FirstName <- person.FirstName
this.MiddleName <- person.MiddleName
this.LastName <- person.LastName
member val FirstName = "" with get, set
member val MiddleName = "" with get, set
member val LastName = "" with get, set
[<EntryPoint>]
let main argv =
// first object
let p1 = Person(FirstName = "John", MiddleName = "Q", LastName = "Public")
printfn "%s %s %s" p1.FirstName p1.MiddleName p1.LastName
// second object is copied from the first, but with a different first name
let p2 = Person(p1, FirstName = "Julian")
printfn "%s %s %s" p2.FirstName p2.MiddleName p2.LastName
0
The output is:
John Q Public
Julian Q Public

polymorphism with types for common fields

Is this question solvable through functional idiomatic approach, could generics or discriminated unions be the answer?
Is it possible to have polymorphism with passing different types to a function while the function is consuming some common fields.
Idea is to be able to call and reuse the function with different types and use the common attributes/fields.
type Car = {
Registration: string
Owner: string
Wheels: int
customAttribute1: string
customAttribute2: string
}
type Truck = {
Registration: string
Owner: string
Wheels: int
customField5: string
customField6: string
}
let SomeComplexMethod (v: Car) =
Console.WriteLine("Registration" + v.Registration + "Owner:" + v.Owner + "Wheels" + v.Wheels
// some complex functionality
Use
SomeComplexMethod(car)
SomeComplexMethod(truck)
Edit
Following the answer. Is it possible to specify the type of the incoming v since JSON serializer asks for the associated type. If Car was supplied as input, Car will be output, If truck as input truck will be output.
let inline someComplexFun v =
let owner = (^v: (member Owner: string)(v))
let registration = (^v: (member Registration: string)(v))
// process input
use response = request.GetResponse() :?> HttpWebResponse
use reader = new StreamReader(response.GetResponseStream())
use memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(reader.ReadToEnd()))
(new DataContractJsonSerializer(typeof<Car>)).ReadObject(memoryStream) :?> Car
if truck was the input v
(new DataContractJsonSerializer(typeof<Truck>)).ReadObject(memoryStream) :?> Truck
This looks like the classical use case for object inheritance, or perhaps an interface. The difference is that an interface provides only methods (including properties, as they are methods under the hood), while a base object (abstract or concrete) can also provide fields.
In your case an interface might be appropriate:
type IVehicle =
abstract Registration : string
abstract Owner : string
abstract Wheels : int
type Car (_r, _o, _w) =
member customAttribute1 : string
member customAttribute2 : string
interface IVehicle with
member Registration = _r
member Owner = _o
member Wheels = _w
type Truck (_r, _o, _w) =
member customField5 : string
member customField6 : string
interface IVehicle with
member Registration = _r
member Owner = _o
member Wheels = _w
let someComplexMethod (v : IVehicle) =
stdout.WriteLine "Registration: " + v.Registration +
"\nOwner: " + v.Owner +
"\nWheels: " + v.Wheels
EDIT: You can do it without OOP by using a discriminated union, and several record types:
type VehicleBase =
{ Registration : string
Owner : string
Wheels : int }
type CarAttributes =
{ customAttribute1 : string
customAttribute2 : string }
type TruckAttributes =
{ customField5 : string
customField6 : string }
type Vehicle =
| Car of VehicleBase * CarAttributes
| Truck of VehicleBase * TruckAttributes
let processVehicle v =
stdout.WriteLine ("Registration: " + v.Registration +
"\nOwner: " + v.Owner +
"\nWheels: " + v.Wheels)
let someComplexMethod = function
| Car (v, _) -> processVehicle v
| Truck (v, _) -> processVehicle v
What you want is usually called structural (or duck) typing. It can be done via interfaces and object expressions in F# (the accepted way) or via SRTPs. The link #CaringDev provided gives you a quick rundown, but obviously you can find many more examples. Please read this and this. For your specific example it will depend how much control you have over the original types.
It's easy to define another type that includes the fields that you might want. Then your function (I found it interesting btw, that you so much want to go for a functional solution but named it a method...) should just take ANY type that has the required fields/properties. Generics won't work for you in this case, as you need to constrain to a subset of types. But once you have such a function, which uses statically resolved type parameters (SRTPs) you're good to go:
type Car = {
Registration: string
Owner: string
Wheels: int
customAttribute1: string
customAttribute2: string
}
type Truck = {
Registration: string
Owner: string
Wheels: int
customField5: string
customField6: string
}
type Bike = {
Owner: string
Color: string
}
type Vehicle = {
Registration: string
Owner: string
}
let inline someComplexFun v =
let owner = (^v: (member Owner: string)(v))
let registration = (^v: (member Registration: string)(v))
{Registration = registration; Owner = owner}
let car = {Car.Registration = "xyz"; Owner = "xyz"; Wheels = 3; customAttribute1= "xyz"; customAttribute2 = "xyz"}
let truck = {Truck.Registration = "abc"; Owner = "abc"; Wheels = 12; customField5 = "abc"; customField6 = "abc"}
let bike = {Owner = "hell's angels"; Color = "black"}
someComplexFun car //val it : Vehicle = {Registration = "xyz";
//Owner = "xyz";}
someComplexFun truck //val it : Vehicle = {Registration = "abc";
//Owner = "abc";}
someComplexFun bike //error FS0001:
The Vehicle type is defined but it could be anything. Then someConplexFun is defined that can take any type, that has Owner and Registration. It has to be inline and its type signature is:
val inline someComplexFun :
v: ^v -> Vehicle
when ^v : (member get_Owner : ^v -> string) and
^v : (member get_Registration : ^v -> string)
You can pass any type that has Owner and Registration fields, and it will return a Vehicle but of course you can just print it out or return a tuple, etc. For the Bike type, since it doesn't have Registration this function will fail.
There are multiple ways how to solve this problem. Besides the already shown solution, i would use lambda functions or a new datatsructure, to solve this problem.
The idea with a lambda is. Instead of a value you expect a function as an argument that returns the needed value. As an example:
let printInformation registration owner wheels obj =
let reg = registration obj
let owner = owner obj
let wheels = wheels obj
printfn "Registration: %s Owner: %s Wheels: %d" reg owner wheels
let car = {Registration="CAR"; Owner="Me"; Wheels=4; customAttribute1="A"; customAttribute2="B"}
let truck = {Registration="TRUCK"; Owner="You"; Wheels=6; customField5="A"; customField6="B"}
printInformation
(fun (obj:Car) -> obj.Registration)
(fun obj -> obj.Owner)
(fun obj -> obj.Wheels)
car
printInformation
(fun (obj:Truck) -> obj.Registration)
(fun obj -> obj.Owner)
(fun obj -> obj.Wheels)
truck
But the whole idea is that you create such a function once for each type, and use partial application.
let printCar =
printInformation
(fun (obj:Car) -> obj.Registration)
(fun obj -> obj.Owner)
(fun obj -> obj.Wheels)
let printTruck =
printInformation
(fun (obj:Truck) -> obj.Registration)
(fun obj -> obj.Owner)
(fun obj -> obj.Wheels)
printCar car
printTruck truck
Based on this you can create a dispatch function, if you wish
let print obj =
match box obj with
| :? Car as c -> printCar c
| :? Truck as t -> printTruck t
| _ -> failwith "Not Car or Truck"
print car
print truck
print "FooBar"
Now the first ttwo works, but you lose type-safety. The third one compiles, but creates a runtime exception.
Working with lambdas is good enough if you only have 1-3 values, but if you need more values, then it can become cumbersome. Another idea would be to create your own data-type for your function, and provide conversation functions instead.
type Information = {
Registration: string
Owner: string
Wheels: int
}
let printInfo (info:Information) =
printfn "Registration: %s Owner: %s Wheels: %d" info.Registration info.Owner info.Wheels
The advantage. Now you relay on data instead of types. You can basically print any type as long you can create an Information record out of it. So its just a matter of providing a single transformation function for each type.
let carToInformation (car:Car) : Information =
{Registration=car.Registration; Owner=car.Owner; Wheels=car.Wheels}
let truckToInformation (truck:Truck) : Information =
{Registration=truck.Registration; Owner=truck.Owner; Wheels=truck.Wheels}
printInfo (carToInformation car)
printInfo (truckToInformation truck)
Sure, you can once again create a dispatch function based on this idea. Its up to you, but my personal approach i would create an Information type and use explicit conversation instead.
In my opinion it is the easiest to understand, and also the most useful one, as you can easily print any type this way as long you somehow can provide the needed data. And your different types don't need to share a common interface with pre-defined fields that have some special logic in it.

Create new object with the same name of the union type

I want create an instance of Person. Person is a type of Animal. When I try to create a Person, the IDE says me "This expression was expected to have type 'Person', but here has type 'Animal'".
type Person(name) =
member this.Name: string = name
type Animal =
| Person of Person
| Cat
| Dog
let person: Person = Person(name = "John")
The problem is that Person refers to both the type and the case of the Discriminated union.
You can invert the definitions so it will resolve to the last one:
type Animal =
| Person of Person
| Cat
| Dog
and
Person (name) =
member this.Name: string = name
let person: Person = Person(name = "John")
// then to create an animal
let animal = Animal.Person (Person(name = "John"))
Alternatives solutions are to use new keyword as #MarcinJuraszek suggested in the comments or considering a different name for the DU case and the type.
In F# names acts as bindings to types and values and at any time you can redefine what a name "points" to. E.g.
// lets define type A
type A(name) = member this.Name : string = name
let x = A("test")
// lets "bind" the type name 'A' to a new type
type A(number) = member this.Number : int = number
let y = A(10)
printfn "type name of x: %s" (x.GetType().Name) // prints 'type name of x: A'
printfn "type name of y: %s" (y.GetType().Name) // prints 'type name of y: A'
So x and y are both of a type named A, but not the same. The same logic applies to Person and Animal.Person, and dependent on the order you define them in, the last defined will be the one referenced when typing Person.
As mentioned, you can use new or definition order to access both. You could also decide to put the Person class in a different module than Animal.
module Inner =
type Person(name) ...
This way you can access your types by prepending the module name.

Why can't F# compiler infer type in this case?

It seems that the p argument in printPerson function can't be inferred to be Person, but intelisense shows for both of printPerson calls that I'm passing p : Person. Help me understand what I'm doing wrong please?
type Person (name:string) =
member e.Name = name
type EmployeeNode =
| Leader of Person * int * list<EmployeeNode>
| Employee of Person * int
let printPerson level p =
printfn "%s %s" <| String.replicate (level) "#" <| p.Name
let rec print node =
match node with
| Employee(p, level) -> printPerson level p
| Leader(p, level, nodes) ->
printPerson level p
List.iter print nodes
Multiple types could have a member this.Name, even if they don't in this example, so the compiler doesn't know that you meant Person. Say for example you had
type Person (name : string) =
member this.Name = name
type School (name : string, address : string) =
member this.Name = name
member this.Address = address
let printName x = printfn "%s" x.Name // This is a type error.
The compiler can't tell which you meant - Person or School. It doesn't matter if you haven't defined another type with a member of the same name, the compiler still won't take the type because things like type extensions can add members onto types after compilation.
Intellisense knows the types you're trying to pass when you call the function, but that's not the same as the compiler enforcing type-safety. In general, any function which accesses class methods or members will need a type annotation for that class.
To fix your example, you just need to change to
let printPerson level p =
to
let printPerson level (p : Person) =
If you are working with simple immutable data containers in F#, you will find it easier to write idiomatic code, making use of type inference, with Records rather than standard .NET classes.
You would change your definition of Person as follows:
type Person = {Name : string}
If you use a record, you do not need to use a type annotation and can keep your code as it is:
let printPerson level p =
printfn "%s %s" <| String.replicate (level) "#" <| p.Name
I would recommend this approach, especially because records give you additional bonuses for free such as automatic structural equality and comparison.
If you use a standard .NET class you must provide a type annotation to disambiguate the specific type you are referring to which exposes the Name property:
type Person (name:string) =
member e.Name = name
let printPerson level (p : Person) =
printfn "%s %s" <| String.replicate (level) "#" <| p.Name
In printPerson, the only information about p the compiler has is that it has a Name member. Since there can be other types than Person which have one, it can't infer p to be Person.
In calls of printPerson the type of p is determined from the pattern, not from the call.

F# Multiple Attributes CLIMutable DataContract

I am running into an issue with combining attributes when using ServiceStack.Redis with f#. Maybe I am thinking about this wrong but right now I'd like my type to be seralized to JSON but also passable to ServicvStack. The issue with f# types is that there is no default constructor and this the data added to my Redis instance is emtpy, well the record is there but none of the data inside it is there.
Here is an example:
open System
open ServiceStack.Redis
[<CLIMutable>]
[<DataContract>]
type Car = {
[<field: DataMember(Name="ID")>]
ID : int64
[<field: DataMember(Name="Make")>]
Make : string
[<field: DataMember(Name="Model")>]
Model : string
}
let redisCar = redis.As<Car>()
let redisAddCar car : Car =
let redisCar = redis.As<Car>()
redisCar.Store({ car with ID = redisCar.GetNextSequence() })
let car1 = redisAddCar { ID = 0L; Make = "Honda"; Model = "Accord LX" }
let car2 = redisAddCar { ID = 0L; Make = "Honda"; Model = "Accord EX" }
let car3 = redisAddCar { ID = 0L; Make = "Honda"; Model = "Accord SX" }
let cars = redisCar.GetAll()
cars |> Seq.iter (fun car -> printfn "ID: %i, Make: %s, Model: %s" car.ID car.Make car.Model)
This will print out:
ID: 0, Make: , Model:
ID: 0, Make: , Model:
ID: 0, Make: , Model:
However if I change the type to this:
[<CLIMutable>]
[<DataContract>]
type Car = {
[<field: DataMember(Name="ID")>]
mutable ID : int64
[<field: DataMember(Name="Make")>]
mutable Make : string
[<field: DataMember(Name="Model")>]
mutable Model : string
}
It will then print out:
ID: 1, Make: Honda, Model: Accord LX
ID: 2, Make: Honda, Model: Accord EX
ID: 3, Make: Honda, Model: Accord SX
Why do I have to add mutable to each property even if it was defined through the attribute? I'd prefer it to not be mutable, as I don't want the state to change. Maybe I am thinking about this too much and should just make a new type and translate the immutable type to the mutable type so it can be consumed with ServiceStack.Redis?
CLIMutable attribute doesn't affect record behavior when record is used from F# code. For F# code it is still immutable record. See here: http://blogs.msdn.com/b/fsharpteam/archive/2012/07/19/more-about-fsharp-3.0-language-features.aspx
"In F# 3.0, we’ve added CLIMutableAttribute. If you attach this
attribute to an F# record type, then the F# compiler emits a default
constructor and property setters into the generated IL for this type
(though those features are not exposed to F# code)."

Resources