On one hand comparing types is overly restrictive i.e. 3 > 1m is not possible because types must always be the same. On the other hand when implementing a custom comparison it is strangely overly liberal because I must do unboxing as in the example:
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? MyThing as y -> compare x.Stamp y.Stamp
| _ -> invalidArg "yobj" "cannot compare values of different types"
Additionally the static member op_GreaterThan is completely ignored.
It does not make sense to me why it should not be possible to compare decimals to integers, furthermore it is possible to use SRTP to call op_GreaterThan.
What was the reason for this design?
Related
What does type X = Y of Z mean in F#? In particular, does the Y token have any material purpose? If I want to express the fact that X is a type backed by the underlying type Z, why do I need Y in that expression?
According to https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/keyword-reference, the of keyword is used to express one of these:
Discriminated Unions
Delegates
Exception Types
Strictly speaking, according to the docs, type X = Y of Z doesn't fall into ANY of the above 3 categories.
It's not Discriminated Union syntax because it's lacking the pipe | character.
It's not a Delegate, because the delegate keyword is absent.
It's not an Exception Type because the exception type is absent.
So it seems like type X = Y of Z is invalid syntax even though it is used pervasively in https://fsharpforfunandprofit.com/posts/conciseness-type-definitions/. Very puzzling - is it that the docs are inaccurate?
Contrary to your intuition, such declaration is, in fact, a discriminated union - one with just one case. Yes, discriminated unions with only one case are totally legal and are sometimes used for type safety or for hiding implementation details.
If you don't want to have that extra Y in there, that is also legal:
type X = Z
This is called "type alias". Its advantage over discriminated union is resource consumption (both performance and memory), but its drawback is that it doesn't provide any extra safety, because X ends up being equivalent and interchangeable with Z in all contexts.
It's not Discriminated Union syntax because it's lacking the pipe | character.
It's possible to omit the first pipe in a Discriminated union:
type DU = A of int | B
This is bad style for standard multi-line definitions but can be appropriate for one-liners. In your example there is only one case so it is possible to omit the pipe completely, which admittedly causes confusion. It would improve clarity to include the bar: type X = | Y of Z
In type X = Y of Z, does the Y token have any material purpose?
Y is used to disambiguate between cases, and for matching against data. If there are are likely to be more cases in future then it makes sense to have this scaffolding for matching. If you know that there will only ever be one case then a DU is not the most appropriate type, since a record type X = { Y: Z } is a simpler construct which achieves the same purpose.
Suppose I have the following DU:
type Something =
| A of int
| B of string * int
Now I use it in a function like this:
let UseSomething = function
| A(i) -> DoSomethingWithA i
| B(s, i) -> DoSomethingWithB s i
That works, but I've had to deconstruct the DU in order to pass it to the DoSomethingWith* functions. It feels natural to me to try to define DoSomethingWithA as:
let DoSomethingWithA (a: Something.A) = ....
but the compiler complains that the type A is not defined.
It seems entirely in keeping with the philosophy of F# to want to restrict the argument to being a Something.A, not just any old int, so am I just going about it the wrong way?
The important thing to note is that A and B are constructors of the same type Something. So you will get inexhaustive pattern matching warning if you try to use A and B cases separately.
IMO, deconstructing all cases of DUs is a good idea since it is type-safe and forces you to think of handling those cases even you don't want to. The problem may arise if you have to deconstruct DUs repetitively in the same way. In that case, defining map and fold functions on DUs might be a good idea:
let mapSomething fa fb = function
| A(i) -> fa i
| B(s, i) -> fb s i
Please refer to excellent Catamorphism series by #Brian to learn about fold on DUs.
That also said that your example is fine. What you really process are string and int values after deconstruction.
You can use Active Patterns to consume two cases separately:
let (|ACase|) = function A i -> i | B _ -> failwith "Unexpected pattern B _"
let (|BCase|) = function B(s, i) -> (s, i) | A _ -> failwith "Unexpected pattern A _"
let doSomethingWithA (ACase i) = ....
but inferred type of doSomethingWithA is still the same and you get an exception when passing B _ to the function. So it's a wrong thing to do IMO.
The other answers are accurate: in F# A and B are constructors, not types, and this is the traditional approach taken by strongly typed functional languages like Haskell or the other languages in the ML family. However, there are other approaches - I believe that in Scala, for example, A and B would actually be subclasses of Something, so you could use those more specific types where it makes sense to do so. I'm not completely sure what tradeoffs are involved in the design decision, but generally speaking inheritance makes type inference harder/impossible (and true to the stereotype type inference in Scala is much worse than in Haskell or the ML languages).
A is not a type, it is just a constructor for Something. There's no way you can avoid pattern matching, which is not necessarily a bad thing.
That said, F# does offer a thing called active patterns, for instance
let (|AA|) = function
| A i -> i
| B _ -> invalidArg "B" "B's not allowed!"
which you can then use like this:
let DoSomethingWithA (AA i) = i + 1
But there's no real reason why you would want to do that! You still do the same old pattern matching under the hood, plus you risk the chance of a runtime error.
In any case, your implementation of UseSomething is perfectly natural for F#.
This function:
let convert (v: float<_>) =
match v with
| :? float<m> -> v / 0.1<m>
| :? float<m/s> -> v / 0.2<m/s>
| _ -> failwith "unknown"
produces an error
The type 'float<'u>' does not have any proper subtypes and cannot be used as the source of a type test or runtime coercion.
Is there any way how to pattern match units of measure?
As #kvb explains in detail, the problem is that units of measure are a part of the type. This means that float<m> is different type than float<m/s> (and unfortunately, this information isn't stored as part of the value at runtime).
So, you're actually trying to write a function that would work with two different types of input. The clean functional solution is to declare a discriminated union that can hold values of either the first type or the second type:
type SomeValue =
| M of float<m>
| MPS of float<m/s>
Then you can write the function using ordinary pattern matching:
let convert v =
match v with
| M v -> v / 0.1<m>
| MPS v -> v / 0.2<m/s>
You'll need to explicitly wrap the values into the discriminated union value, but it's probably the only way to do this directly (without making some larger changes in the program structure).
For normal types like int and float, you could also use overloaded members (declared in some F# type), but that doesn't work for units of measure, because the signature will be the same after the F# compiler erases the unit information.
There are two problems with your approach. First of all, when you use an underscore in the definition of your function, that's the same as using a fresh type variable, so your definition is equivalent to the following:
let convert (v: float<'u>) = //'
match v with
| :? float<m> -> v / 0.1<m>
| :? float<m/s> -> v / 0.2<m/s>
| _ -> failwith "unknown"
What the error message is telling you is that the compiler know that v is of type float<'u>, and float<'u> has no proper subtypes, so there's no point in doing a type test to determine if it's a float<m> or any other type.
You might try to get around this by first boxing v into an object and then doing a type test. This would work, for instance, if you had a list<'a> and wanted to see if it were a list<int>, because full type information about generic objects is tracked at runtime including generic type parameters (notably, this is different from how some other runtimes like Java's work). Unfortunately, F# units of measure are erased at runtime, so this won't work here - there is no way for the system to infer the correct measure type given a boxed representation, since at runtime the value is just a plain float - F#'s system for units of measure is actually quite similar in this respect to how Java handles generic types.
As an aside, what you're trying to do seems quite suspect - functions which are generic in the unit of measure shouldn't do different things depending on what the measure type is; they should be properly parametric. What exactly are you trying to achieve? It certainly doesn't look like an operation which corresponds to physical reality, which is the basis for F#'s measure types.
See the Units at Runtime Section at http://msdn.microsoft.com/en-us/library/dd233243.aspx.
I agree with #kvb, I think the best way around this is to pass an object.
What I would like to do, using your code structure:
let convert (v: float<_>) =
match v with
| :? float<m> -> v<m>
| :? float<inches> -> v * 2.54 / 100.0<m>
I have a function of the form
'a -> ('a * int) list -> int
let rec getValue identifier bindings =
match bindings with
| (identifier, value)::tail -> value
| (_, _)::tail -> getValue identifier tail
| [] -> -1
I can tell that identifier is not being bound the way I would like it to and is acting as a new variable within the match expression. How to I get identifier to be what is passed into the function?
Ok! I fixed it with a pattern guard, i.e. | (i, value)::tail when i = indentifier -> value
but I find this ugly compared to the way I originally wanted to do it (I'm only using these languages because they are pretty...). Any thoughts?
You can use F# active patterns to create a pattern that will do exactly what you need. F# supports parameterized active patterns that take the value that you're matching, but also take an additional parameter.
Here is a pretty stupid example that fails when the value is zero and otherwise succeeds and returns the addition of the value and the specified parameter:
let (|Test|_|) arg value =
if value = 0 then None else Some(value + arg)
You can specify the parameter in pattern matching like this:
match 1 with
| Test 100 res -> res // 'res' will be 101
Now, we can easily define an active pattern that will compare the matched value with the input argument of the active pattern. The active pattern returns unit option, which means that it doesn't bind any new value (in the example above, it returned some value that we assigned to a symbol res):
let (|Equals|_|) arg x =
if (arg = x) then Some() else None
let foo x y =
match x with
| Equals y -> "equal"
| _ -> "not equal"
You can use this as a nested pattern, so you should be able to rewrite your example using the Equals active pattern.
One of the beauties of functional languages is higher order functions. Using those functions we take the recursion out and just focus on what you really want to do. Which is to get the value of the first tuple that matches your identifier otherwise return -1:
let getValue identifier list =
match List.tryFind (fun (x,y) -> x = identifier) list with
| None -> -1
| Some(x,y) -> y
//val getValue : 'a -> (('a * int) list -> int) when 'a : equality
This paper by Graham Hutton is a great introduction to what you can do with higher order functions.
This is not directly an answer to the question: how to pattern-match the value of a variable. But it's not completely unrelated either.
If you want to see how powerful pattern-matching could be in a ML-like language similar to F# or OCaml, take a look at Moca.
You can also take a look at the code generated by Moca :) (not that there's anything wrong with the compiler doing a lot of things for you in your back. In some cases, it's desirable, even, but many programmers like to feel they know what the operations they are writing will cost).
What you're trying to do is called an equality pattern, and it's not provided by Objective Caml. Objective Caml's patterns are static and purely structural. That is, whether a value matches the pattern depends solely on the value's structure, and in a way that is determined at compile time. For example, (_, _)::tail is a pattern that matches any non-empty list whose head is a pair. (identifier, value)::tail matches exactly the same values; the only difference is that the latter binds two more names identifier and value.
Although some languages have equality patterns, there are non-trivial practical considerations that make them troublesome. Which equality? Physical equality (== in Ocaml), structural equality (= in Ocaml), or some type-dependent custom equality? Furthermore, in Ocaml, there is a clear syntactic indication of which names are binders and which names are reference to previously bound values: any lowercase identifier in a pattern is a binder. These two reasons explain why Ocaml does not have equality patterns baked in. The idiomatic way to express an equality pattern in Ocaml is in a guard. That way, it's immediately clear that the matching is not structural, that identifier is not bound by this pattern matching, and which equality is in use. As for ugly, that's in the eye of the beholder — as a habitual Ocaml programmer, I find equality patterns ugly (for the reasons above).
match bindings with
| (id, value)::tail when id = identifier -> value
| (_, _)::tail -> getValue identifier tail
| [] -> -1
In F#, you have another possibility: active patterns, which let you pre-define guards that concern a single site in a pattern.
This is a common complaint, but I don't think that there's a good workaround in general; a pattern guard is usually the best compromise. In certain specific cases there are alternatives, though, such as marking literals with the [<Literal>] attribute in F# so that they can be matched against.
F# keyword 'Some' - what does it mean?
Some is not a keyword. There is an option type however, which is a discriminated union containing two things:
Some which holds a value of some type.
None which represents lack of value.
It's defined as:
type 'a option =
| None
| Some of 'a
It acts kind of like a nullable type, where you want to have an object which can hold a value of some type or have no value at all.
let stringRepresentationOfSomeObject (x : 'a option) =
match x with
| None -> "NONE!"
| Some(t) -> t.ToString()
Can check out Discriminated Unions in F# for more info on DUs in general and the option type (Some, None) in particular. As a previous answer says, Some is just a union-case of the option<'a> type, which is a particularly common/useful example of an algebraic data type.
Some is used to specify an option type, or in other words, a type that may or may not exist.
F# is different from most languages in that control flow is mostly done through pattern matching as opposed to traditional if/else logic.
In traditional if/else logic, you may see something like this:
if (isNull(x)) {
do ...
} else { //x exists
do ...
}
With pattern matching logic, matching we need a similar way to execute certain code if a value is null, or in F# syntax, None
Thus we would have the same code as
match x with
| None -> do ...
| Some x -> do ...