I'm trying to generate lists of dates (time periods) in F# and I found my answer at (F# generate a sequence/array of dates) and it works perfectly.
However I cannot wrap my ahead around the definition of the (+) static member.
static member (+) (d:DateTime, Span wrapper) = ...
Particularly the Span wrapper portion. I even re-wrote is as:
static member (+) (d:DateTime, wrapper:Span) = ...
and even though it compiles (fsi) it does not work.
Only when I rewrote it to match the original syntax it does work as expected.
I looked at the MSDN docs as well as some of the F# books I have but I cannot find anything that explains that particular syntax for the (+) operator.
For the context, here is original example:
type Span =
| Span of TimeSpan
static member (+) (d:DateTime, Span wrapper) = d + wrapper
static member Zero = Span(new TimeSpan(0L))
In (+), the author uses pattern matching directly on the argument. It means that wrapper has type of TimeSpan, and d + wrapper is an operation between DateTime and TimeSpan
The example looks clearer in the following verbose form:
static member (+) (d:DateTime, span: Span) =
match span with
| Span wrapper ->
d + wrapper
This is quite subtle syntactic trick that you can use with type definitions of the following form:
type MyNumber = MyNumber of int
This defines a type MyNumber which is an integer wrapped using a constructor that is also named MyNumber. So, we are defining a type and a constructor of the same name. We could use different names:
type MyNumberType = MyNumberCtor of int
The following syntax is used for pattern matching when you are extracting the value. Here, we are using the constructor:
let getNumber (MyNumber n) = n
let getNumber (MyNumberCtor n) = n
The following syntax is type annotation (which uses the type name):
let doNothing (n:MyNumber) = 1
let getNumber (n:MyNumberType) = 1
Here, we cannot do much with n, because it is the wrapped value - so we'd have to use pattern matching to extract it. As you can see in the answer from #pad, the other way to write the pattern matching is to use the match construct. In any case, there is nothing special related to the operators and types - it is just a naming trick that people sometimes use when defining wrappers.
Related
I've been reading F# articles and they use single case variants to create distinct incompatible types. However in Ocaml I can use private module types or abstract types to create distinct types. Is it common in Ocaml to use single case variants like in F# or Haskell?
Another specialized use case fo a single constructor variant is to erase some type information with a GADT (and an existential quantification).
For instance, in
type showable = Show: 'a * ('a -> string) -> showable
let show (Show (x,f)) = f x
let showables = [ Show (0,string_of_int); Show("string", Fun.id) ]
The constructor Show pairs an element of a given type with a printing function, then forget the concrete type of the element. This makes it possible to have a list of showable elements, even if each elements had a different concrete types.
For what it's worth it seems to me this wasn't particularly common in OCaml in the past.
I've been reluctant to do this myself because it has always cost something: the representation of type t = T of int was always bigger than just the representation of an int.
However recently (probably a few years) it's possible to declare types as unboxed, which removes this obstacle:
type [#unboxed] t = T of int
As a result I've personally been using single-constructor types much more frequently recently. There are many advantages. For me the main one is that I can have a distinct type that's independent of whether it's representation happens to be the same as another type.
You can of course use modules to get this effect, as you say. But that is a fairly heavy solution.
(All of this is just my opinion naturally.)
Yet another case for single-constructor types (although it does not quite match your initial question of creating distinct types): fancy records. (By contrast with other answers, this is more a syntactic convenience than a fundamental feature.)
Indeed, using a relatively recent feature (introduced with OCaml 4.03, in 2016) which allows writing constructor arguments with a record syntax (including mutable fields!), you can prefix regular records with a constructor name, Coq-style.
type t = MakeT of {
mutable x : int ;
mutable y : string ;
}
let some_t = MakeT { x = 4 ; y = "tea" }
(* val some_t : t = MakeT {x = 4; y = "tea"} *)
It does not change anything at runtime (just like Constr (a,b) has the same representation as (a,b), provided Constr is the only constructor of its type). The constructor makes the code a bit more explicit to the human eye, and it also provides the type information required to disambiguate field names, thus avoiding the need for type annotations. It is similar in function to the usual module trick, but more systematic.
Patterns work just the same:
let (MakeT { x ; y }) = some_t
(* val x : int = 4 *)
(* val y : string = "tea" *)
You can also access the “contained” record (at no runtime cost), read and modify its fields. This contained record however is not a first-class value: you cannot store it, pass it to a function nor return it.
let (MakeT fields) = some_t in fields.x (* returns 4 *)
let (MakeT fields) = some_t in fields.x <- 42
(* some_t is now MakeT {x = 42; y = "tea"} *)
let (MakeT fields) = some_t in fields
(* ^^^^^^
Error: This form is not allowed as the type of the inlined record could escape. *)
Another use case of single-constructor (polymorphic) variants is documenting something to the caller of a function. For instance, perhaps there's a caveat with the value that your function returns:
val create : unit -> [ `Must_call_close of t ]
Using a variant forces the caller of your function to pattern-match on this variant in their code:
let (`Must_call_close t) = create () in (* ... *)
This makes it more likely that they'll pay attention to the message in the variant, as opposed to documentation in an .mli file that could get missed.
For this use case, polymorphic variants are a bit easier to work with as you don't need to define an intermediate type for the variant.
I have some types that enforce numeric value ranges, and I use them in many files in a single project. They look something like this:
[<Struct>]
type NonNegativeMoney =
new(x) =
if x < 0m then invalidArg "x" "Ruh-roh..."
{ Value = x }
val Value : decimal
static member (+) (x: NonNegativeMoney, y: NonNegativeMoney) = NonNegativeMoney(x.Value + y.Value)
I now want to make these types internal to the assembly and leave only my OO type model public. However, when I flip these types to internal, I got the following compiler error:
The member or object constructor 'op_Addition' is not public. Private
members may only be accessed from within the declaring type. Protected
members may only be accessed from an extending type and cannot be
accessed from inner lambda expressions.
The reason for this, has been addressed in the question Why does the F# compiler fail with this infix operator?. The solution proposed in the answer is to use F# signature files to make the types internal. This works for the OP's scenario in that question, where usage of the operator is limited to a type in the same file. However, I can't seem to find a way to make it work so the operator is accessible from all files in my project. If I use a signature file, it works intra-file, but not inter-file.
Is there any way to make this work so the types are internal to the assembly, but visible across the files in my project? I'd like to keep the operators, as I'm using library functions like Seq.sum that require them on the types being summed.
You can define the overload in a module instead of inside the type:
[<Struct>]
type internal NonNegativeMoney =
new(x) =
if x < 0m then invalidArg "x" "Ruh-roh..."
{ Value = x }
val Value : decimal
let internal (+) (x: NonNegativeMoney) (y: NonNegativeMoney) = NonNegativeMoney(x.Value + y.Value)
...but this will override the normal (+) operator, which is probably why you ruled it out. Using a custom operator (like ++) may be a reasonable compromise.
You can make the operator available to the whole project by marking the module [<AutoOpen>].
In my F# application I often need to perform a case-insensitive search of a string within a string, so I created a function with the appropriate comparison:
let indexOf (str:string) (value:string) startIndex =
match str.IndexOf(value, startIndex, StringComparison.OrdinalIgnoreCase) with
| index when index >= 0 -> Some index
| _ -> None
I do not like the fact, that when I want to search from the beginning, I have to pass the redundant 0 as the start index.
I am relatively new to both F# and the functional programming, so I would like to know what is the preferred (cleanest) solution from the functional point of view?
Create two versions:
let indexOfFrom (str:string) (value:string) startIndex = (...)
let indexOf str value = indexOfFrom str value 0
Use Option type:
let foundIndex = indexOf "bar foobar" "bar" (Some 4)
Create a dedicated discriminated union:
type Position =
| Beginning
| StartIndex of index : int
let foundIndex = indexOf "bar foobar" "bar" (Index 4)
Place the 'indexOf' function inside a type and use the 'classic' overloading.
Place the 'indexOf' function inside a type and use F# optional arguments.
If you are defining the functionality as F# functions, then I think that using two separate functions (with reasonably descriptive names) is probably the best option you have. So I'd go with your first option (I definitely prefer this option over defining a discriminated union just for this single purpose):
let indexOfFrom (str:string) (value:string) startIndex = (...)
let indexOf str value = indexOfFrom str value 0
The alternative is to define the functionality as members of a type - then you can use both overloading and F# optional arguments, but you'd have to access them using full name String.IndexOf. You could write something like:
type String =
static member IndexOf(str:string, value:string, startIndex) = (...)
static member IndexOf(str, value) = String.IndexOf(str, value, 0)
Or, using optional parameters:
type String =
static member IndexOf(str:string, value:string, ?startIndex) = (...)
Which of the options is the best one?
If you're designing functional API (e.g. domain-specific language), then your option with two separate functions is probably the best choice.
If you're aiming to design a nice F# API, then I think your option (multiple functions) or optional parameters are quite reasonable. Functions are used quite heavily in Deedle and F# Charting relies on optional arguments.
The benefit of using overloading is that the library will be also nicely usable from C#. So, if you're thinking of calling the library from C#, this is pretty much the only option.
I think option 1 (with curried function) would be simplest. Curried functions are pretty common in functional programming.
In options 2 or 3 you'll still have to pass additional parameter to the function for the search from the beginning
Options 4 or 5 require additional overhead to create type. It's kind of 'overkill' for this simple task
I am trying to understand the following code, particularly StringConstant:
type StringConstant = StringConstant of string * string
[<EntryPoint>]
let main argv =
let x = StringConstant("little", "shack")
printfn "%A" x
0 // return an integer exit code
(By way of context, StringConstant is used in the FParsec tutorial, but this example does not use FParsec.)
What I would like to know is:
what exactly is the type statement doing?
once I instantiate x, how would I access the individual "parts"
("little" or "house")
As others already noted, technically, StringConstant is a discriminated union with just a single case and you can extract the value using pattern matching.
When talking about domain modelling in F#, I like to use another useful analogy. Often, you can start just by saying that some data type is a tuple:
type Person = string * int
This is really easy way to represent data, but the problem is that when you write "Tomas", 42, the compiler does not know that you mean Person, but instead understands it as string * int tuple. One-case discriminated unions are a really nice way to name your tuple:
type Person = Person of string * int
It might be a bit confusing that this is using the name Person twice - first as a type name and second as a name of the case. This has no special meaning - it simply means that the type will have the same name as the case.
Now you can write Person("Tomas", 42) to create a value and it will have a type Person. You can decompose it using match or let, but you can also easily write functions that take Person. For example, to return name, you can write:
let getName (Person(name, _)) =
name
I think single-case discriminated unions are often used mainly because they are really easy to define and really easy to work with. However, I would not use them in code that is exposed as a public API because they are a bit unusual and may be confusing.
PS: Also note that you need to use parentheses when extracting the values:
// Correct. Defines symbols 'name' and 'age'
let (Person(name, age)) = tomas
// Incorrect! Defines a function `Person` that takes a tuple
// (and hides the `Person` case of the discriminated union)
let Person(name, age) = tomas
StringConstant is a discriminated union type, with just a single case (also named StringConstant). You extract the parts via pattern matching, using match/function or even just let, since there is just a single case:
let (StringConstant(firstPart, secondPart)) = x
type StringConstant = StringConstant of string * string
results in a discriminated union with one type.
type StringConstant = | StringConstant of string * string if you execute it in F# interactive.
You can see the msdn documentation on that here.
You can get the value out like this:
let printValue opt =
match opt with
| StringConstant( x, y) -> printfn "%A%A" x y
The other guys already mentioned how you extract the data from a discriminated union, but to elaborate a little more on Discriminated unions one could say that they are sorta like enums on steroids. They are implemented behind the scenes as a type hierarchy where the type is the base class and the cases are subclases of that baseclass with whatever parameter they might have as readonly public variables.
In Scala a similar data-structure is called case classes which might help you convince yourself of this implementationmethod.
One nice property of discriminated unions are that they are self-referenceable and therefor are perfect for defining recursive structures like a tree. Below is a definition of a Hoffman coding tree in just three lines of code. Doing that in C# would probably take somewhere between 5 and 10 times as many lines of code.
type CodeTree =
| Branch of CodeTree * CodeTree * list<char> * int
| Leaf of char * int
For information about Discriminated Unions see the msdn documentation
For an example of using Discriminated Unions as a tree-structure see this gist which is an implementation of a huffman decoder in roughly 60 lines of F#)
In F# what is the type annotation for a typed list (e..g list of int)? With a simple function I can do annotations as follows:
let square(x:int) = ...
I've annotated x as an int type. But what if I want to do a type annotation for an int list? For example, let's say I have a max function that expects a list - how would I do a type annotation for it?
let max(numbers:??) = ...
There are two options:
let max (numbers:int list) = ...
let max (numbers:list<int>) = ...
The first version uses syntax that is inherited from OCaml (and is frequently used for primitive F# types such as lists). The second version uses .NET syntax (and is more frequently used for .NET types or when writing object-oriented code in F#). However, both of them mean exactly the same thing.
In any case, the form of type annotation is always (<something> : <type>) where <something> is either a pattern (as in parameter list) or an expression. This means that int list and list<int> are just names of types. F# Interactive prints the type if you enter some value, so you can use this to learn more about how type names are written:
> [1;2;3]
val it : int list = [ 1; 2; 3 ]