Structural dependency in F# ---- possible without mutable and nullable fields? - f#

I would like to have two types that have each other as fields:
type Player<'Team>(team:'Team) =
member this.Team = team
type DoublesTeam(playerA:Player<DoublesTeam>, playerB:Player<DoublesTeam>) =
member this.PlayerA = playerA
member this.PlayerB = playerB
(This is parametrised to break the circular dependency between types).
Question: how to create instances of these types so that they point to one another?
In C# this would be clear: create two Players without assigning the Team field (i.e. leave it null), create a Team passing two Players in the constructor and manually set their Team fields to the Team instance. To do so in F# the Team field would need to be mutable and nullable or an option type. This is highly undesirable.
Is there a way to do this without making one of the fields nullable or an option type?

You won't be able to do it in exactly that form with classes. However, if you switch to records, it's easy:
type Player<'Team> = { team:'Team }
type DoublesTeam = { playerA:Player<DoublesTeam>; playerB:Player<DoublesTeam> }
let rec t1 = {playerA = p1; playerB = p2 }
and p1 = { team = t1 }
and p2 = { team = t1 }
Note that you can do it with classes, but you have to introduce a delay of some form; the easiest way is probably to add a touch of laziness:
type Player<'Team>(team:Lazy<'Team>) =
member this.Team = team.Value
type DoublesTeam(playerA:Lazy<Player<DoublesTeam>>, playerB:Lazy<Player<DoublesTeam>>) =
member this.PlayerA = playerA.Value
member this.PlayerB = playerB.Value
let rec t1 = DoublesTeam(lazy p1, lazy p2)
and p1 = Player(lazy t1)
and p2 = Player(lazy t1)

Related

F# use named tuple as function parameter

I have the following type in F#:
type CodeNameError(CodeNameCombination: (Code*Name)[]) =
member this.CodeNameCombinations = CodeNameCombination
Is there a way to turn the (Code*Name)[] into a named tuple array in F#?
In c# I would do something like:
public CodeNameError((Code code, Name name)[] codeName)
{
CodeNameCombination = codeName
}
F# does not have named tuples in the same way in which C# has them, but there are a couple of alternatives. My preferred option would actually be to just define a new record type for the Code * Name pair. If you get into a situation where you want to name things, a record is a good choice and it takes 1 line of code:
type NamedCode = { Name:Name; Code:Code }
type CodeNameError(codeNameCombination:NamedCode[]) =
member this.CodeNameCombinations = codeNameCombination
CodeNameError [| { Code = "1+1"; Name = "test" } |]
If you do not want to define a type (but I'm not sure why you wouldn't want to do this), you could use anonymous records:
type CodeNameError(CodeNameCombination: {| code:Code; name:Name |}[]) =
member this.CodeNameCombinations = CodeNameCombination
CodeNameError [| {| code = "1+1"; name = "test" |} |]

F# sequence with at least one element

Beginner in F# here
I want to create a type, which is a sequence of another concrete type (Event) with at least one element. Any other elements can be added anytime later. Normally in C# I would create a class with a private List<Event> and public methods.
But I want to do it with a functional approach and not imitate the C# approach. Or at least try.
My train of thought:
Let's create a type "of seq" and give it a constructor requiring instance of the Event type
type Event = Event of string
type PublishedEvents = EventList of seq<Event> with
static member create (event:Event) = EventList(Seq.singleton event)
Now let's add an "add" method for adding another optional Event instances
type PublishedEvents with
member this.add(event:Event) = Seq.append this [event]
But that doesn't work, F# complains that "this" is not compatible with seq<'a>.
So I tried this:
type PublishedEvents with
member this.add (event:Event) : PublishedEvents = EventList(Seq.append this [event])
Now it complains that "this" is not compatible with seq<Event>...which is confusing me now since few lines above it says EventList of seq<Event> ... so I guess I need to somehow convert EventList back to seq<Event> so I can then use Seq.append ?
let convertFunction (eventList:PublishedEvents) : seq<Event> = ???
But I have no idea how to do this.
Am I even going the right direction? Is it better for this to mimic a C# class with a backing field? Or am I missing something?
The actual sequence of events is wrapped inside an EventList discriminated union case.
You can unwrap it and re-wrap it like this:
type PublishedEvents with
member this.add(event:Event) =
match this with
| EventList events -> Seq.append events [event] |> EventList
However, I have to question the value of creating this PublishedEvents type in the first place, if it's just a single EventList case containing a sequence that requires you to wrap and unwrap values repeatedly.
Also, please be aware that this add method doesn't change the existing PublishedEvents. It creates a new one with a new sequence of events, because of the way that Seq.append works, because seq<'a> is actually just F#'s name for System.Collections.Generic.IEnumerable<'a>).
Furthermore, your approach does not prevent creation of a non-empty event sequence. EventList is a public constructor for PublishedEvents so you can just write:
EventList []
A simple way to make the type system enforce a non-empty sequence is this:
type NonEmptySeq<'a> = { Head : 'a; Tail : seq<'a> } with
static member Create (x:'a) = { Head = x; Tail = [] }
member this.Add x = { this with Tail = Seq.append this.Tail [x] }
let a = NonEmptySeq.Create (Event "A")
let b = a.Add (Event "B")
But again, these sequences are immutable. You could do something similar with a C# List<'a> if you need mutation. In F# it's called a ResizeArray<'a>:
type NonEmptyResizeArray<'a> = { Head : 'a; Tail : ResizeArray<'a> } with
static member Create (x:'a) = { Head = x; Tail = ResizeArray [] }
member this.Add x = this.Tail.Add x
let a = NonEmptyResizeArray.Create (Event "A")
a.Add (Event "B")
I propose that you go even more functional and not create members for your types - have it done in your functions. For example this would achieve the same and I would argue it's more idiomatic F#:
type Event = Event of string
type PublishedEvents = EventList of Event * Event list
let create e = EventList (e,[])
let add (EventList(head,tail)) e = EventList(e,head::tail)
let convert (EventList(head,tail)) = head::tail |> Seq.ofList
let myNewList = create (Event "e1")
let myUpdatedList = add myNewList (Event "e2")
let sequence = convert myUpdatedList
val sequence : seq = [Event "e2"; Event "e1"]
On the other hand if your aim is to interop with C# your approach would be easier to consume on C# side.

Constructing and deconstructing records

The msdn page documenting Records (F#) details record expressions for record construction and record patterns for deconstruction, the latter without naming them as such.
Here's an example which uses both techniques for an arithmetic operator:
// Simple two-dimensional generic vector defintion
type 'a UV =
{ U : 'a; V : 'a }
static member inline (+) ({ U = au; V = av }, { U = bu; V = bv }) =
{ U = au + bu; V = av + bv }
This appears unwieldy and not very readable. For deconstruction, there are dot-notation or functions as alternatives. Since the dot-notation operator has a special dispensation in section 8.4.2 Name Resolution and Record Field Labels of the spec (an expression’s type may be inferred from a record label), there's normally no need to annotate. Accessor functions like let u { U = u } = u wouldn't give us any advantages then.
For construction, I think a case can be made for a function as record constructor. Access to the original constructor might even be restricted:
type 'a UV =
internal { U : 'a; V : 'a }
let uv u v = { U = u; V = v }
type 'a UV with
static member inline (+) (a, b) =
uv (a.U + b.U) (a.V + b.V)
Is this an idiomatic thing to do? How to package such functions in modules and handle namespace issues?
Short answer: I don't think there is a general convention here at the moment so it will be a personal decision in the end.
To summarise what you get for free with records in F# is:
Construct: { U = u; V = v } (bracket-notation)
Deconstruct: let u = record.u (dot-notation) and let {U = u} = record (pattern matching)
Update: {record with U = u} (bracket-notation)
But you don't get first class functions for free, if you want you can code them by hand.
The following is what I would personally use as convention:
A static member New with curried arguments for record construction.
For update and deconstruction I would use some kind of Lenses abstraction.
Here's an example of the code I would have to add by hand:
// Somewhere as a top level definition or in a base library
type Lens<'T,'U> = {Get: 'T -> 'U; Set: 'U -> 'T -> 'T } with
member l.Update f a = l.Set (f (l.Get a)) a
type UV<'a> = {U : 'a; V : 'a } with
// add these static members to your records
static member New u v : UV<'a> = {U = u; V = v}
static member u = {Get = (fun (x: UV<'a>) -> x.U); Set = fun t x -> {x with U = t}}
static member v = {Get = (fun (x: UV<'a>) -> x.V); Set = fun t x -> {x with V = t}}
let uvRecord = UV.New 10 20
let u = UV.u.Get uvRecord
let uvRecord1 = UV.u.Set (u+1) uvRecord
let uvRecord2 = UV.u.Update ((+)1) uvRecord
This way I would have first class functions for construction, deconstruction but also for updates plus other very interesting Lenses properties as you can read in this post.
UPDATE (in response to your comments)
Of course they can be defined later, what does it change?
The same applies for the New constructor, it can be defined later but that's actually a good thing.
The accessor functions you defined can also be defined later, indeed any first-class getter, setter or updater value can be defined later.
Anyway the answer to your question is "no, there are no conventions" the rest it's a personal decision, which would be my decision and also many Haskellers are pushing to get some kind of automatic Lenses for Haskell records.
Why would I decide to go this way? Because in terms of lines of code the effort of adding a simple accessor function is almost the same as adding a get-Lens, so for the same price I get more functionality.
If you are not happy with the Lenses discussion please tell me, I can delete it and leave the short answer, or I can delete the whole answer too if it's confusing instead of clarifying.
Or may be I misunderstood your question, for me your question was about which convention is generally used to add first-class constructors, getters and setters values for records.
Composition is not the only advantage of Lenses, you can do many things, keep reading about them, they provide a very interesting abstraction and not only restricted to records.

Can I define a record type in terms of another?

type ProcessParametersPair = {Definition:string; Provided:string}
type QueryResult = { DefinitionId:int;DefinitionName:string; ProcessTemplateId:int; StatusName:string; DefinitionArgs:string; BuildArgs:string;
StatusCode:int option;cleanWorkspaceOption:string; RawProcessParameters:ProcessParametersPair; lastBuild:Tbl_Build}
type QueryDisplay = { DefinitionId:int;DefinitionName:string; ProcessTemplateId:int; StatusName:Object; DefinitionArgs:string; BuildArgs:string;
StatusCode:int option;cleanWorkspaceOption:string; RawProcessParameters:Object; lastBuild:Object}
do I really have to repeat all fields of the QueryDisplayRecord that match? Can I do something like you can do with record instances? type QueryDisplay = {QueryResult with lastBuild:Object}
In this case I'm varying record based on a field type, I'd also love to know if I can do this but on added fields instead of type changed fields.
I am not referring to instances, I'm referring to Record type definitions.
Are either of these possible?
A record type cannot "inherit" from another type. You could put all the common fields in a separate type and reference it:
type Common = { A: int; B: int }
type Record1 = { Common: Common; C: int }
type Record2 = { Common: Common; D: int }
Or use classes:
type Common(a, b) =
member val A = a
member val B = b
type Class1(a, b, c) =
inherit Common(a, b)
member val C = c
type Class2(a, b, d) =
inherit Common(a, b)
member val D = d

Critique of immutable classes with circular references design, and better options

I have a factory class that creates objects with circular references. I'd like them to be immutable (in some sense of the word) too. So I use the following technique, using a closure of sorts:
[<AbstractClass>]
type Parent() =
abstract Children : seq<Child>
and Child(parent) =
member __.Parent = parent
module Factory =
let makeParent() =
let children = ResizeArray()
let parent =
{ new Parent() with
member __.Children = Seq.readonly children }
[Child(parent); Child(parent); Child(parent)] |> children.AddRange
parent
I like this better than an internal AddChild method because there's a stronger guarantee of immutability. Perhaps it's neurotic, but I prefer closures for access control.
Are there any pitfalls to this design? Are there better, perhaps less cumbersome, ways to do this?
You can use F#'s support for recursive initialization even when creating an instance of abstract class:
let makeParent() =
let rec children = seq [ Child(parent); Child(parent); Child(parent) ]
and parent =
{ new Parent() with
member __.Children = children }
parent
When compiling the code, F# uses lazy values, so the value children becomes a lazy value and the property Children accesses the value of this lazy computation. This is fine, because it can first create instance of Parent (referencing the lazy value) and then actually construct the sequence.
Doing the same thing with records wouldn't work as nicely, because none of the computations would be delayed, but it works quite nicely here, because the sequence is not actually accessed when creating the Parent (if it was a record, this would be a field that would have to be evaluated).
The F# compiler cannot tell (in general) whether this is correct, so it emits a warning that can be disabled using #nowarn "40".
In general, I think that using let rec .. and .. to initialize recursive values is a good thing - it is a bit limited (one of the references must be delayed), but it forces you to keep the recursive references isolated and, I think, it keeps your code simpler.
EDIT To add an example when this may go wrong - if the constructor of Child tries to access the Children collection of its parent, then it forces evaluation of the lazy value before it can be created and you get a runtime error (which is what the warning says). Try adding this to the constructor of Child:
do printfn "%d" (Seq.length parent.Children)
I think that Tomas's answer is the way to go. However, for completeness I'll show how you could use recursive records to create cyclic immutable objects. This can potentially get quite ugly, so I've hidden the immutable record implementation behind some nicer properties:
type Parent = internal { children : Children option }
and internal Children = { first : Child; rest : Children option }
and Child = internal { parent : Parent }
let rec internal listToChildren = function
| [] -> None
| c::cs -> Some { first = c; rest = listToChildren cs }
let rec internal childrenToList = function
| None -> []
| Some { first = c; rest = cs } -> c::(childrenToList cs)
module Factory =
let makeParent() =
let rec parent = { children = children }
and child1 = { parent = parent }
and child2 = { parent = parent }
and child3 = { parent = parent }
and children = [child1; child2; child3] |> listToChildren
parent
type Parent with
member p.Children = childrenToList p.children
type Child with
member c.Parent = c.parent
I guess something like this can also be done:
type ParentFactory private (n) as X =
inherit Parent()
let childs = [for i=1 to n do yield Child(X :> Parent)]
override X.Children = childs |> List.toSeq;
static member Create n = (new ParentFactory(n)) :> Parent

Resources