Suppose I have nested Elmish components like this: A contains B contains C.
Then if C has state and messages, these must be passed from C to B and then to A.
For example, the message and model types for B might be:
type Message =
| CMessage of C.Message
| UpdateFoo of string
type Model =
{
Foo : string
C : C.Model
}
Then update for B will do some routing:
let update message model =
match message with
| CMessage m ->
{
model with
C = C.update m model.C
}
| UpdateFoo foo -> { model with Foo = foo }
Then the same must be done for A consuming B messages.
This is quite verbose compared to setState, for example.
What are some strategies for managing this in Elmish?
If you create a hierarchy of model types, then you need to route messages through that hierarchy in update. If you don't want to route messages through that hierarchy in update, then don't create a hierarchy of model types. That would mean you have a flat model.
However, I think that having a flat model is not sustainable. As your application grows in complexity, you will need to manage that complexity by grouping related concepts into (sub-)modules that contain their own model types.
This is quite verbose compared to setState, for example. What are some strategies for managing this in Elmish?
The function setState is meant for library authors. Your question is about specific model and message types, so my impression is that you are an "end user" of Elmish (instead of a library author). As such, I think it is unfair to compare your example update function to some alternative that uses setState since you should be using setState.
I think this verboseness you describe is the tradeoff for tightly controlling mutation. By using Elmish, you are saying that you want to tightly control mutation (by letting nearly all of it happen in Elmish instead of your code), so I think think this verboseness is necessary.
Related
I am currently doing the exercism.io F# track. For everyone who doesn't know it, it's solving small problems TDD style to learn or improve a programming language.
The last two tasks were about the usage of classes in F# (or types as they are called in F#). One of the tasks uses a BankAccount that has a balance and a status (open/closed) and can be altered by using functions. The usage was like this (Taken from the test code):
let test () =
let account = mkBankAccount () |> openAccount
Assert.That(getBalance account, Is.EqualTo(Some 0.0)
I wrote the code that makes the test pass using an immutable BankAccount class that can be interacted with using free functions:
type AccountStatus = Open | Closed
type BankAccount (balance, status) =
member acc.balance = balance
member acc.status = status
let mkBankAccount () =
BankAccount (0.0, Closed)
let getBalance (acc: BankAccount) =
match acc.status with
| Open -> Some(acc.balance)
| Closed -> None
let updateBalance balance (acc: BankAccount) =
match acc.status with
| Open -> BankAccount (acc.balance + balance, Open)
| Closed -> failwith "Account is closed!"
let openAccount (acc: BankAccount) =
BankAccount (acc.balance, Open)
let closeAccount (acc: BankAccount) =
BankAccount (acc.balance, Closed)
Having done a lot of OO before starting to learn F# this one got me wondering. How do more experienced F# developers use classes? To make answering this question more simple, here are my main concerns about classes/types in F#:
Is the use of classes in a typical OO fashion discouraged in F#?
Are immutable classes preferred? ( I found them to be confusing in the above example)
What is the preferred way to access/alter class data in F#? (Class member functions and get/set or free functions which allow piping? What about static members to allow piping and providing the functions with a fitting namespace?)
I'm sorry if the question is vague. I don't want to develop bad coding habits in my functional code and i need a starting point on what good practices are.
Is the use of classes in a typical OO fashion discouraged in F#?
It's not discouraged, but it's not the first place most experienced F# developers would go. Most F# developers will avoid subclassing and OO paradigms, and instead go with records or discriminated unions, and functions to operate on them.
Are immutable classes preferred?
Immutability should be preferred when possible. That being said, immutable classes can often be represented other ways (see below).
What is the preferred way to access/alter class data in F#? (Class member functions and get/set or free functions which allow piping? What about static members to allow piping and providing the functions with a fitting namespace?)
This is typically done via functions that allow piping, though access can be done directly, as well.
For your above code, it would be more common to use a record instead of a class, and then put the functions which work on the record into a module. An "immutable class" like yours can be written as a record more succinctly:
type BankAccount = { balance : float ; status : AccountStatus }
Once you've done this, working with it becomes easier, as you can use with to return modified versions:
let openAccount (acc: BankAccount) =
{ acc with status = Open }
Note that it'd be common to put these functions into a module:
module Account =
let open acc =
{ acc with status = Open }
let close acc =
{ acc with status = Closed }
Question: Is the use of classes in a typical OO fashion discouraged in F#?
It is not against F#'s nature. I think that there are cases when this is justified.
However, usage of classes should be limited if developers want to take full advantage of F# strengths (e.g. type interference, ability to use functional patterns such as partial application, brevity) and are not constrained by legacy systems and libraries.
F# for fun and profit gives a quick summary of pros and cons of using classes.
Ouestion: Are immutable classes preferred? ( I found them to be confusing in the above example)
Sometimes yes, sometimes not. I think that immutability of classes gives you lots of advantages (it's easier to reason about type's invariants etc.) but sometimes immutable class can be a bit cumbersome to use.
I think that this question is a bit too broad - it's somewhat similar to a question if fluent interfaces are preferred in object-oriented design - the short answer is: it depends.
What is the preferred way to access/alter class data in F#? (Class member functions and get/set or free functions which allow piping? What about static members to allow piping and providing the functions with a fitting namespace?)
Piping is a canonical construct in F#, so I would go for static member. If your library is consumed in some other languages, you should include getter and setter inside class as well.
EDIT:
FSharp.org has a list of quite specific design guidelines which include:
✔ Do use classes to encapsulate mutable state, according to standard
OO methodology.
✔ Do use discriminated unions as an alternative to class hierarchies
for creating tree-structured data.
There are a few ways of looking at this question.
This could mean several things. For POCO's, immutable F# records are preferred. Then the operations on them return new records with the requisite fields changed.
type BankAccount { status: AccountStatus; balance: int }
let close acct = { acct with status = Closed } // returns a *new* acct record
So that means you've got to get past the idea of an account "object" that represents a single "thing". It's just data that you operate on to create different data, and eventually (likely) store into a database somewhere.
So rather than the OO paradigm acct.Close(); acct.PersistChanges(), you'd have let acct' = close acct; db.UpdateRecord(acct').
For "services" in a "service-oriented architecture (SOA)" however, interfaces and classes are perfectly natural in F#. For instance, if you want a Twitter API, you'd probably create a class that wraps all the HTTP calls just like you would in C#. I've seen some references to the "SOLID" ideology in F# that eschews SOA completely but I've never figured out how to make that work in practice.
Personally, I like an FP-OO-FP sandwich with Suave's FP combinators on top, a SOA using Autofac in the middle, and FP records on the bottom. I find that works well and is scalable.
FWIW also you may want do make your BankAccount a discriminated union, if Closed can't have a balance. Try this out in your code samples. One of the nice things in F# is it makes illogical states unrepresentable.
type BankAccount = Open of balance: int | Closed
I am looking to encode (in some .NET language -- fsharp seems most likely to support) a class of types that form a current context.
The rules would be that we start with an initial context of type 'a. As we progress through the computations the context will be added to, but in a way that I can always get previous values. So assume an operation that adds information to the context, 'a -> 'b, that infers that all elements of 'a are also in 'b.
The idea is similar to an immutable map, but I would like it to be statically typed. Is that feasible? How, or why not? TIA.
Update: The answer appears to be that you cannot quite do this at this time, although I have some good suggestions for modeling what I am looking for in a different way. Thanks to all who tried to help with my poorly worded question.
Separate record types in F# are distinct, even if superficially they have similar structure. Even if the fields of record 'a form a subset of fields of record 'c, there's no way of enforcing that relationship statically. If you have a valid reason to use distinct record types there, the best you could do would be to use reflection to get the fields using FSharpType.GetRecordFields and check if one forms the subset of the other.
Furthermore, introducing a new record type for each piece of data added would result in horrendous amounts of boilerplate.
I see two ways to model it that would feel more at place in F# and still allow you some way of enforcing some form of your 'a :> 'c constraint at runtime.
1) If you foresee a small number of records, all of which are useful in other parts of your program, you can use a discriminated union to enumerate the steps of your process:
type NameAndAmountAndFooDU =
| Initial of Name
| Intermediate of NameAndAmount
| Final of NameAndAmountAndFoo
With that, records that previously were unrelated types 'a and 'c, become part of a single type. That means you can store them in a list inside Context and easily go back in time to see if the changes are going in the right direction (Initial -> Intermediate -> Final).
2) If you foresee a lot of changes like 'adding' a single field, and you care more about the final product than the intermediate ones, you can define a record of option fields based on the final record:
type NameAndAmountAndFooOption =
{
Name: string option
Amount: decimal option
Foo: bool option
}
and have a way to convert it to a non-option NameAndAmountAndFoo (or the intermediate ones like NameAndAmount if you need them for some reason). Then in Context you can set the values of individual fields one at a time, and again, collect the previous records to keep track of how changes are applied.
Something like this?
type Property =
| Name of string
| Amount of float
let context = Map.empty<string,Property>
//Parse or whatever
let context = Map.add "Name" (Name("bob")) context
let context = Map.add "Amount" (Amount(3.14)) context
I have a feeling that if you could show us a bit more of your problem space, there may be a more idiomatic overall solution.
F# computation expressions have the syntax:
ident { cexpr }
Where ident is the builder object (this syntax is taken from Don Syme's 2007 blog entry).
In all the examples I've seen, builder objects are singleton instances, and stateless to boot. Don gives the example of defining a builder object called attempt:
let attempt = new AttemptBuilder()
My question: Why doesn't F# just use the AttemptBuilder class directly in computation expressions? Surely the notation could be de-sugared to static method calls just as easily as instance method calls.
Using an instance value means that one could in theory instantiate multiple builder objects of the same class, presumably parameterised in some way, or even (heaven forbid) with mutable internal state. But I can't imagine how that would ever be useful.
Update: The syntax I quoted above suggests the builder must appear as a single identifier, which is misleading and probably reflects an earlier version of the language. The most recent F# 2.0 Language Specification defines the syntax as:
expr { comp-or-range-expr }
which makes it clear that any expression (that evaluates to a builder object) can be used as the first element of the construct.
Your assumption is correct; a builder instance can be parameterized, and parameters can be subsequently used throughout the computation.
I use this pattern for building a tree of mathematical proof to a certain computation. Each conclusion is a triple of a problem name, a computation result, and a N-tree of underlying conclusions (lemmas).
Let me provide with a small example, removing a proof tree, but retaining a problem name. Let's call it annotation as it seems more suitable.
type AnnotationBuilder(name: string) =
// Just ignore an original annotation upon binding
member this.Bind<'T> (x, f) = x |> snd |> f
member this.Return(a) = name, a
let annotated name = new AnnotationBuilder(name)
// Use
let ultimateAnswer = annotated "Ultimate Question of Life, the Universe, and Everything" {
return 42
}
let result = annotated "My Favorite number" {
// a long computation goes here
// and you don't need to carry the annotation throughout the entire computation
let! x = ultimateAnswer
return x*10
}
It's just a matter of flexibility. Yes, it would be simpler if the Builder classes were required to be static, but it does take some flexibility away from developers without gaining much in the process.
For example, let's say you want to create a workflow for communicating with a server. Somewhere in the code, you'll need to specify the address of that server (a Uri, an IPAddress, etc.). In which cases will you need/want to communicate with multiple servers within a single workflow? If the answer is 'none' then it makes more sense for you to create your builder object with a constructor which allows you to pass the Uri/IPAddress of the server instead of having to pass that value around continuously through various functions. Internally, your builder object might apply the value (the server's address) to each method in the workflow, creating something like (but not exactly) a Reader monad.
With instance-based builder objects, you can also use inheritance to create type hierarchies of builders with some inherited functionality. I haven't seen anyone do this in practice yet, but again -- the flexibility is there in case people need it, which you wouldn't have with statically-typed builder objects.
One other alternative is to make use of single case discriminated unions as in :
type WorkFlow = WorkFlow with
member __.Bind (m,f) = Option.bind f m
member __.Return x = Some x
then you can directly use it like
let x = WorkFlow{ ... }
I came across the original statement of the Liskov Substitution Principle on Ward's wiki tonight:
What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T." - Barbara Liskov, Data Abstraction and Hierarchy, SIGPLAN Notices, 23,5 (May, 1988).
I've always been crap at parsing predicate logic (I failed Calc IV the first time though), so while I kind of understand how the above translates to:
Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
what I don't understand is why the property Liskov describes implies that S is a subtype of T and not the other way around.
Maybe I just don't know enough yet about OOP, but why does Liskov's statement only allow for the possibility S -> T, and not T -> S?
the hypothetical set of programs P (in terms of T) is not defined in terms of S, and therefore it doesn't say much about S. On the other hand, we do say that S works as well as T in that set of programs P, and so we can draw conclusions about S and its relationship to T.
One way to think about this is that P demands certain properties of T. S happens to satisfy those properties. Perhaps you could even say that 'every o1 in S is also in T'. This conclusion is used to define the word subtype.
As pointed by sepp2k there are multiple views explaining this in the other post.
Here are my two cents about it.
I like to look at it this way
If for each object o1 of type TallPerson there is an object o2 of type Person such that for all programs P defined in terms of Person, the behavior of P is unchanged when o1 is substituted for o2 then TallPerson is a subtype of Person. (replacing S with TallPerson and T with Person)
We typically have a perspective of objects deriving some base class have more functionality, since its extended. However with more functionality we are specializing it and reducing the scope in which they can be used thus becoming subtypes to its base class(broader type).
A derived class inherits its base class's public interface and is expected to either use the inherited implementation or to provide an implementation that behaves similarly (e.g., a Count() method should return the number of elements regardless of how those elements are stored.)
A base class wouldn't necessarily have the interface of any (let alone all) of its derived classes so it wouldn't make sense to expect an arbitrary reference to a base class to be substitutable for a specified derived class. Even if it appears that only the subset of the interface that supported by the base class's interface is required, that might not be the case (e.g., it could be that a shadowing method in the specific derived class is referred to).
Earlier I requested some feedback on my first F# project. Before closing the question because the scope was too large, someone was kind enough to look it over and leave some feedback.
One of the things they mentioned was pointing out that I had a number of regular functions that could be converted to be methods on my datatypes. Dutifully I went through changing things like
let getDecisions hand =
let (/=/) card1 card2 = matchValue card1 = matchValue card2
let canSplit() =
let isPair() =
match hand.Cards with
| card1 :: card2 :: [] when card1 /=/ card2 -> true
| _ -> false
not (hasState Splitting hand) && isPair()
let decisions = [Hit; Stand]
let split = if canSplit() then [Split] else []
let doubleDown = if hasState Initial hand then [DoubleDown] else []
decisions # split # doubleDown
to this:
type Hand
// ...stuff...
member hand.GetDecisions =
let (/=/) (c1 : Card) (c2 : Card) = c1.MatchValue = c2.MatchValue
let canSplit() =
let isPair() =
match hand.Cards with
| card1 :: card2 :: [] when card1 /=/ card2 -> true
| _ -> false
not (hand.HasState Splitting) && isPair()
let decisions = [Hit; Stand]
let split = if canSplit() then [Split] else []
let doubleDown = if hand.HasState Initial then [DoubleDown] else []
decisions # split # doubleDown
Now, I don't doubt I'm an idiot, but other than (I'm guessing) making C# interop easier, what did that gain me? Specifically, I found a couple disadvantages, not counting the extra work of conversion (which I won't count, since I could have done it this way in the first place, I suppose, although that would have made using F# Interactive more of a pain). For one thing, I'm now no longer able to work with function "pipelining" easily. I had to go and change some |> chained |> calls to (some |> chained).Calls etc. Also, it seemed to make my type system dumber--whereas with my original version, my program needed no type annotations, after converting largely to member methods, I got a bunch of errors about lookups being indeterminate at that point, and I had to go and add type annotations (an example of this is in the (/=/) above).
I hope I haven't come off too dubious, as I appreciate the advice I received, and writing idiomatic code is important to me. I'm just curious why the idiom is the way it is :)
Thanks!
One practice I used in my F# programming is use the code in both places.
The actual implementation is natural to be put in a module:
module Hand =
let getDecisions hand =
let (/=/) card1 card2 = matchValue card1 = matchValue card2
...
and give a 'link' in the member function/property:
type Hand
member this.GetDecisions = Hand.getDecisions this
This practice is also generally used in other F# libraries, e.g. the matrix and vector implementation matrix.fs in powerpack.
In practice, not every function should be put in both places. The final decision should be based on the domain knowledge.
Regarding the top-level, the practice is to put functions in to modules, and make some of them in the top-level if necessary. E.g. in F# PowerPack, Matrix<'T> is in the namespace Microsoft.FSharp.Math. It is convenient to make a shortcut for the matrix constructor in the toplevel so that the user can construct a matrix directly without opening the namespace:
[<AutoOpen>]
module MatrixTopLevelOperators =
let matrix ll = Microsoft.FSharp.Math.Matrix.ofSeq ll
An advantage of members is Intellisense and other tooling that makes members discoverable. When a user wants to explore an object foo, they can type foo. and get a list of the methods on the type. Members also 'scale' easier, in the sense that you don't end up with dozens of names floating around at the top level; as program size grows, you need more names to only be available when qualified (someObj.Method or SomeNamespace.Type or SomeModule.func, rather than just Method/Type/func 'floating free').
As you've seen, there are disadvantages as well; type inference is especially notable (you need to know the type of x a priori to call x.Something); in the case of types and functionality that is used very commonly, it may be useful to provide both members and a module of functions, to have the benefits of both (this is e.g. what happens for common data types in FSharp.Core).
These are typical trade-offs of "scripting convenience" versus "software engineering scale". Personally I always lean towards the latter.
This is a tricky question and both of the approaches have advantages and disadvantages. In general, I tend to use members when writing more object-oriented/C# style code and global functions when writing more functional code. However, I'm not sure I can clearly state what the difference is.
I would prefer using global functions when writing:
Functional data types such as trees/lists and other generally useable data structures that keep some larger amount of data in your program. If your type provides some operations that are expressed as higher order functions (e.g. List.map) then it is probably this kind of data type.
Not type-related functionality - there are situations when some operations don't strictly belong to one particular type. For example, when you have two representations of some data structure and you're implementing transformation between the two (e.g. typed AST and untyped AST in a compiler). In that case, functions are better choice.
On the other hand, I would use members when writing:
Simple types such as Card that can have properties (like value and color) and relatively simple (or no) methods performing some computations.
Object-oriented - when you need to use object-oriented concepts, such as interfaces, then you'll need to write the functionality as members, so it may be useful to consider (in advance) whether this will be the case for your types.
I would also mention that it is perfectly fine to use members for some simple types in your application (e.g. Card) and implement the rest of the application using top-level functions. In fact, I think that this would probably be the best approach in your situation.
Notably, it is also possible to create a type that has members together with a module that provides the same functionality as functions. This allows the user of the library to choose the style he/she prefers and this is completely valid approach (however, it probably makes sense for stand-alone libraries).
As a side-note, chaining of calls can be achieved using both members and functions:
// Using LINQ-like extension methods
list.Where(fun a -> a%3 = 0).Select(fun a -> a * a)
// Using F# list-processing functions
list |> List.filter (fun a -> a%3 = 0) |> List.map (fun a -> a * a)
I generally avoid classes primarily because of the way members cripple type inferencing. If you do this, it is sometimes handy to make the module name the same as the type name - the compiler directive below comes in handy.
type Hand
// ...stuff...
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Hand =
let GetDecisions hand = //...