-
Notifications
You must be signed in to change notification settings - Fork 0
Varianttypes
OCaml laat aan de programmeur toe, zelf nieuwe types te definiëren. Het belangrijkste soort types dat je in OCaml kunt definiëren heet varianttypes. Bijvoorbeeld:
type seizoen = Winter | Lente | Zomer | Herfst
Deze definitie definieert het varianttype seizoen
, alsook de vier constructoren van dit type: Winter
, Lente
, Zomer
, en Herfst
. Er zijn dus vier waarden van dit type.
Om met varianttypes te werken, kan je match
-uitdrukkingen gebruiken, net zoals voor lijsten. (Het type van lijsten in OCaml is eigenlijk gewoon een voorgedefinieerd varianttype.) Bijvoorbeeld: de volgende functie berekent de tekstvoorstelling van een seizoen:
let tekst_van_seizoen seizoen =
match seizoen with
Winter -> "winter"
| Lente -> "lente"
| Zomer -> "zomer"
| Herfst -> "herfst"
Opdracht:
- Tik
tekst_van_seizoen Winter
in. - OCaml antwoordt met
- : string = "winter"
.
Oefening:
- Definieer de functie
volgend_seizoen
die het seizoen, volgend op een gegeven seizoen, berekent.
Constructoren van een varianttype kunnen argumenten hebben. De volgende types laten bijvoorbeeld toe de stand van een spel in een tennismatch bij te houden:
type speler = Serveerder | Ontvanger
type score = Nul | Vijftien | Dertig | Veertig
type stand =
Regulier of score * score
| Voordeel of speler
| Gewonnen of speler
Hierbij stelt Regulier Vijftien Dertig
bijvoorbeeld voor dat de serveerder vijftien punten heeft, en de ontvanger dertig.
De volgende functie berekent, gegeven een stand, de nieuwe stand nadat de serveerder een rally wint:
let plus_punt_serveerder score =
match score with
Regulier (Nul, scoreOntvanger) -> Regulier (Vijftien, scoreOntvanger)
| Regulier (Vijftien, scoreOntvanger) -> Regulier (Dertig, scoreOntvanger)
| Regulier (Dertig, scoreOntvanger) -> Regulier (Veertig, scoreOntvanger)
| Regulier (Veertig, Veertig) -> Voordeel Serveerder
| Regulier (Veertig, scoreOntvanger) -> Gewonnen Serveerder
| Voordeel Serveerder -> Gewonnen Serveerder
| Voordeel Ontvanger -> Regulier Veertig Veertig
Merk op dat de functie plus_punt_serveerder
het geval dat er al een speler gewonnen heeft, afhandelt. In dat geval gooit de functie een MatchFailure
.
Oefening:
- Definieer de functie
plus_punt_ontvanger
. Probeer hierbij de functieplus_punt_serveerder
te hergebruiken, door functiesandere_speler
enomgekeerde_stand
te definiëren.
Argumenten van een constructor van een varianttype kunnen zelf ook weer van dat varianttype zijn. We spreken dan van een recursief varianttype. Een gekend voorbeeld hiervan is het type van de lijsten. Het type van de lijsten van getallen zouden we zelf als volgt kunnen definiëren:
type getallenlijst = LegeGetallenLijst | NietLegeGetallenLijst of int * getallenlijst
let rec getallenlijst_aan_elkaar getallen1 getallen2 =
match getallen1 with
LegeGetallenLijst -> getallen2
| NietLegeGetallenLijst (kop, staart) -> NietLegeGetallenLijst (kop, getallenlijst_aan_elkaar staart getallen2)
Ziehier een ander voorbeeld van een recursief varianttype:
type uitdrukking =
GetalUitdrukking of int
| SomUitdrukking of uitdrukking * uitdrukking
| VerschilUitdrukking of uitdrukking * uitdrukking
| ProductUitdrukking of uitdrukking * uitdrukking
| QuotientUitdrukking of uitdrukking * uitdrukking
Dit type laat toe eenvoudige uitdrukkingen voor te stellen:
| Uitdrukking | Voorstelling als waarde van type 'uitdrukking'
+------------------+-----------------------------------------------
| 42 | GetalUitdrukking 42
| 42 + 3 | SomUitdrukking (GetalUitdrukking 42, GetalUitdrukking 3)
| 42 - 3 | VerschilUitdrukking (GetalUitdrukking 42, GetalUitdrukking 3)