Pokémon fight each other, and they have types:
And some others, but we'll ignore than for now
Depending on their type, they do more or less damage. Let's write some OCaml code to model Pokémon.
(* [ptype] is the pokemon's type *)
type ptype = TNormal | TFire | TWater
(* [peff] represents a pokemon's effectiveness *)
type peff = ENormal | ENotVery | ESuper
type ptype = TNormal | TFire | TWater
type peff = ENormal | ENotVery | ESuper
We can't have them both be called Normal, because they would shadow each other, so we're calling one ENormal and one TNormal for Effectiveness and Type
let mult_of_eff = function
| ENormal -> 1.0
| ENotVery -> 0.5
| ESuper -> 2.0
val mult_of_eff : peff -> float = <fun>
In OCaml, it's idiomatic to write mult_of_eff rather than mult_to_eff.
Next, let's encode the table of effectiveness of attacks
let eff = function
| (TFire, TFire) -> ENotVery
| (TWater, TWater) -> ENotVery
| (TFire, TWater) -> ENotVery
| (TWater, TFire) -> ESuper
| _ -> ENormal
val eff : ptype * ptype -> peff = <fun>
We could also rewrite this function to use or patterns:
let eff = function
| (TFire, TFire) | (TWater, TWater) | (TFire, TWater) -> ENotVery
| (TWater, TFire) -> ESuper
| _ -> ENormal
val eff : ptype * ptype -> peff = <fun>
Now let's calculate the effectiveness of some pairs
eff (TFire, TFire);;
- : peff = ENotVery
You might also want to write it as a function that takes each argument separately
let eff t1 t2 = match t1, t2 with
| TFire, TFire | TWater, TWater | TFire, TWater -> ENotVery
| TWater, TFire -> ESuper
| _ -> ENormal
val eff : ptype -> ptype -> peff = <fun>
eff TWater TFire
- : peff = ESuper
This is a topic called Currying. You can read more in the textbook.
Now let's implement a type for an actual pokémon!
type mon = {
name: string;
hp: int;
ptype: ptype;
}
type mon = { name : string; hp : int; ptype : ptype; }
let charmander = {
name = "Charmander";
hp = 39;
ptype = TFire;
}
val charmander : mon = {name = "Charmander"; hp = 39; ptype = TFire}
Now we have Charmander modeled as an actual pokémon!