Skip to content

Varianttypes

Bart Jacobs edited this page Feb 16, 2018 · 7 revisions

Varianttypes

Seizoenen

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.

Tennisscores

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 functie plus_punt_serveerder te hergebruiken, door functies andere_speler en omgekeerde_stand te definiëren.

Recursieve varianttypes

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)

Uitdrukkingen

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)
Clone this wiki locally