Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static members vs module for type in F#?

Tags:

f#

Suppose I have a type like this:

type Season =
| Spring
| Summer
| Autumn
| Winter

I want to have a function next that returns the next season:

let next s = 
  match s with
  | Spring -> Summer
  | Summer -> Autumn
  | Autumn -> Winter
  | Winter -> Spring

There are two places I can put this function.

In a named module:

module Season = 
  let next s = 
    match s with
    | Spring -> Summer
    | Summer -> Autumn
    | Autumn -> Winter
    | Winter -> Spring

Or as a static member on the type:

type Season =
| Spring
| Summer
| Autumn
| Winter
  with 
    static member next s = 
      match s with
      | Spring -> Summer
      | Summer -> Autumn
      | Autumn -> Winter
      | Winter -> Spring

What are the reasons to favour each approach?

like image 747
sdgfsdh Avatar asked Dec 30 '18 16:12

sdgfsdh


People also ask

What happens if non-static members are used in static member function?

We can access the static member function using the class name or class' objects. If the static member function accesses any non-static data member or non-static member function, it throws an error. Here, the class_name is the name of the class.

Can we call static member function of a class using object of a class?

A static member function can be called even if no objects of the class exist and the static functions are accessed using only the class name and the scope resolution operator ::. A static member function can only access static data member, other static member functions and any other functions from outside the class.

Can static members be inherited C++?

Quick A: Yes, and there are no ambiguity with static members.

What is static member and static member function in C++?

A static member function is a special member function, which is used to access only static data members, any other normal data member cannot be accessed through static member function. Just like static data member, static member function is also a class function; it is not associated with any class object.


1 Answers

Ultimately that's a domain modelling judgement call and there's no one definite correct answer here. What matters is how each choice affects readability and maintainability of the code.

I tend to favor static members for functionality that is highly "cohesive" with the type, more so than any particular piece of business logic code. Think Parse functions or smart constructors/factory methods. The general approach being that if I were to refactor the code by moving the type somewhere else, those would be the functions I'd definitely want to move together with it. Having them as static members also helps discoverability through intellisense, as you only need to know the name of the type to find them.

On the other hand, I'd use a module to house business logic that represents some abstract process, and if the function in question is somehow specific to that business logic and unlikely to be useful outside of it, then I'd go with a function in a module even if it's still somewhat type specific. For instance, a very purpose-specific parser that's only useful as part of this one workflow for legacy reasons would be a let-bound function rather than a static member, because other clients that use that type generally shouldn't even know about that function.

In your case, I'd go with the static member Next if it makes sense for it to be used in multiple different modules in your context - if being able to cycle through Seasons is a fundamental quality that defines what a Season is.

Otherwise if you just have a single module, let's say WeatherPatterns, that adjusts rainfall based on season changes, and that's the only part of your code where you care about cycling through Seasons, then I'd put it as a function in that module.

like image 189
scrwtp Avatar answered Nov 15 '22 22:11

scrwtp