F# why is cast needed? - f#

I'm new to F# and working through this article. In this article there is a sample of the following recursive type:
type Book = {title: string; price: decimal}
type ChocolateType = Dark | Milk | SeventyPercent
type Chocolate = {chocType: ChocolateType ; price: decimal}
type WrappingPaperStyle =
| HappyBirthday
| HappyHolidays
| SolidColor
type Gift =
| Book of Book
| Chocolate of Chocolate
| Wrapped of Gift * WrappingPaperStyle
| Boxed of Gift
| WithACard of Gift * message:string
Which is used in the following way:
let wolfHall = {title="Wolf Hall"; price=20m}
let birthdayPresent = WithACard (Wrapped (Book wolfHall, HappyBirthday), "Happy Birthday")
What I don't understand: Why do I need to cast wolfHall to a Book? The compiler should know that wolfHall is a Book, and therefore a Gift, based on the beforehand let-assignment.
Thanks

In your code, Book means two things:
It's the name of the record type with two fields, title and price.
It's one of the cases of the discriminated union Gift. This particular case is of type Book (the record type), and it's named Book. It doesn't have to be named the same, but it can be (and often is - the same is true of the next case, Chocolate).
So, you're not casting wolfHall. You're constructing an instance of Gift, using the particular case constructor which happens to be named the same as the type it wraps. The compiler knows the difference and usually when you're reading the code, you can tell the difference. But if it's confusing, you can certainly name that constructor something else.

Related

What is the correct designation for values of discriminated union types?

Consider this type definition:
type ChoiceOne =
| A
| B
and this binding
let c1 = A
I assume the correct way to translate this into natural language would be "the value A of type ChoiceOne is constructed and bound to the name c1".
Now take a look at this next type definition and binding:
type ChoiceTwo =
| A of int
| B of float
let c1 = A 1
I now see several ways of describing what is going on here:
"the value A of type ChoiceTwo is constructed ..." ( and what about the 1 ? )
"the value 1 of type ChoiceTwo is constructed ..." ( and what about the A ? )
"the value A of type ChoiceTwo with the ( inner value ? associated value ? ... ) 1 is constructed ..."
I guess option 3 describes the situation best, but how can I correctly designate the value 1 with respect to the (other?) value A of type ChoiceTwo ?
Here's the terminology that I use, which I believe is widely accepted, using my own example:
type MyDU =
| A of int
| B
A is a case
A is also a function that takes an int and returns a value of type MyDU
Therefore, A 1 is a value of type MyDU
B is a case
B is also a value of type MyDU
The only words needed here are "case", "value", "function" and "type". Don't use the word "construct". In general, when talking about F# code, if you can accurately replace any words that you use with the ones that I recommend, then do so!
This is all splitting hairs. Nobody really cares about how exactly to say these things outside of a quiz in college, and even then, I would recommend maybe transferring to a different college :-)
But if you really want to split hairs, here we go.
In your very first example, the value A is not "constructed". Since it doesn't have parameters, there can be only one instance of it, and that instance always exists, so there is no need to "construct" it.
To be sure, A may still be referred to as a "constructor", but it's also a "value" at the same time.
In the second example, it is sometimes said that "a value A 1 was constructed", but more often "a value A constructed with parameter 1"

An issue with type matching (hopefully possible to fix) F#

So i have type Gitem
type Gitem =
|Weapon of Weapon
|Bomb of Bomb
|Monster of Monster
|Armour of Armour
|Potion of Potion
|None
This is used to store different types of objects within a record, to be clear, the types I'm having issues with look like so:
type Monster={
name:string;
dVal:float;
dType:DamType;
hVal:float;
info:string;
dInfo:string;
dCry:string;
Special:bool;
sItem:obj;
}
type Armour={
name:string;
aVal:float;
dType:DamType;
info:string;
iSpace:int;
hidden:bool;
}
type Weapon={
name:string;
dVal:float;
dType:DamType;
info:string;
iSpace:int;
hidden:bool;
}
The problem is, Gitem includes Monster as a potential type, however monsters can have a bomb, weapon or armour as their sItem, i made the type object due to this.
Later in my code i write :
match monster.sItem with //gives them the item if the monster drops one
| Bomb bomb ->
procBomb bomb
| Weapon weap ->
procWeap weap
| Potion pot ->
procPot pot
| Armour arm ->
procArm arm
I get the error that the expression should be Gitem, not obj, however I cannot make the monster sitem field as Gitem, it is not allowed due to Gitem using monster as a possible type. I tried making another type like Gitem that has all types apart from monster, however this causes problems too.
I'm second year of university, any help would be appreciated
Mutual recursive types can be declared using the and keyword:
type A = { b : B }
and B = { a : A option }
Also, F# 4.1 introduced recursive modules (and namespaces), which allow mutual recursive types at a module (namespace) level. This is useful if you have many lengthy mutually dependent types (note that there’s noand):
module rec RecursiveModule =
type A = { b : B }
type B = { a : A option }

Compare types and process functions depending on type of input F#

I have a list of rooms that each contain an object that is either a weapon, bomb or monster, is there a way I can check which type is contained, and then call on different functions depending on this? Below is a previous attempt to do so.
let ritemprocess (a:Room) =
match a.item.GetType with
| Bomb -> procBomb(a.item)
Here I am looking at the item of a room, and if it is a bomb I call the process bomb function, which requires type bomb as an input to work, however the error I get is that a.item is type object not type Bomb.
Type room is like so:
type Room = {
id:int;
item:obj;
n:int;
e:int;
s:int;
w:int;
complete:bool;
}
F# is statically typed; when your Room type says item is of type obj, it's precisely that, you can't use it in a context that would require something that is not an obj. There is a way of circumventing it with run-time type casting:
let ritemprocess (a:Room) =
match a.item with
| :? Bomb as bomb -> procBomb bomb
...
but usually it would be considered a code smell when it happens as part of your domain model.
A typical approach would be to have a discriminated union to model your item type:
type Item =
| Weapon of Weapon
| Bomb of Bomb
| Monster of Monster
type Room = {
id:int;
item:Item;
n:int;
e:int;
s:int;
w:int;
complete:bool;
}
assuming Weapon/Bomb/Monster are types the already exist in your code. Then you just match on the Item type cases:
let ritemprocess (a:Room) =
match a.item with
| Bomb bomb -> procBomb bomb
...

A very basic Type check fails in F# ... why?

I wrote this code
type Test =
| Age of int
| Name of string;;
let x = Age(10);;
if (x.GetType() = typeof<Test>) then printfn "true" else printfn "false";;
The code prints false. But that puzzles me because isn't Age of type Test?
Also, is there a better way to compare types in F# the .GetType() = typeof<> is very long. I tried :? but I think that's for typecasting rather than comparing types.
The plain answer is, do so:
if (x :> obj) :? Test then printfn "true" else printfn "false"
This issue comes because of the implementation of DUs (using internal classes and tags) and the limitation of F#'s type system (which does not acknowledge the implementation).
As you saw, the type of x is FSI_0001+Test+Age, and F# does not recognize that as a sub-type of Test.
Quoting from the spec
A compiled union type U has:
· One CLI static getter property U.C for each null union case C. This
property gets a singleton object that represents each such case.
· One CLI nested type U.C for each non-null union case C. This type
has instance properties Item1, Item2.... for each field of the union
case, or a single instance property Item if there is only one field.
However, a compiled union type that has only one case does not have a
nested type. Instead, the union type itself plays the role of the case
type.
We see that Age is implemented as a nested type of the parent DU. As a result you could use Type.GetNestedTypes to get all the subtypes of the DU and then test each one to see if the type matches.
But that puzzles me because isn't Test of type Color?
There is no type Color and Test is a type itself so it does not have a type. So your question is nonsensical.
Perhaps you meant to ask why the answer is what it is? If so, it is a consequence of the way F# currently chooses to represent such values internally.

Understanding F# StringConstant

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#)

Resources