Zoeken…


Opmerkingen

Een van de sterke punten van Haskell is de mogelijkheid om het type systeem te gebruiken om delen van uw probleemdomein in het type systeem te modelleren. Daarbij kom je vaak zeer complexe typen tegen. Bij het schrijven van programma's met deze typen (dat wil zeggen met waarden met deze typen) wordt het soms bijna niet te wijzigen om met alle typen te 'jongleren'. Vanaf GHC 7.8 is er een nieuwe syntactische functie genaamd getypte gaten. Getypte gaten veranderen de semantiek van de kerntaal niet; ze zijn puur bedoeld als hulpmiddel bij het schrijven van programma's.

Zie de Haskell-wiki voor een diepgaande uitleg van getypte gaten en een bespreking van het ontwerp van getypte gaten.


Sectie van de GHC-gebruikershandleiding over getypte gaten .

Syntaxis van getypte gaten

Een getypt gat is een enkel onderstrepingsteken ( _ ) of een geldige Haskell-id die niet binnen het bereik valt, in een expressiecontext. Voorafgaand aan het bestaan van getypte gaten, zouden beide dingen een fout veroorzaken, dus de nieuwe syntax interfereert niet met een oude syntax.

Controle van het gedrag van getypte gaten

Het standaardgedrag van getypte gaten is het produceren van een compilatie-fout bij het tegenkomen van een getypt gat. Er zijn echter verschillende vlaggen om hun gedrag aan te passen. Deze vlaggen zijn als volgt samengevat ( GHC trac ):

Standaard heeft GHC getypte gaten ingeschakeld en produceert een compileerfout wanneer het een getypt gat tegenkomt.

Wanneer -fdefer-type-errors of -fdefer-typed-holes is ingeschakeld, worden hole-fouten geconverteerd naar waarschuwingen en resulteren in runtime-fouten bij evaluatie.

De waarschuwingsvlag -fwarn-typed-holes is standaard ingeschakeld. Zonder -fdefer-type-errors of -fdefer-typed-holes deze vlag een no-op, omdat getypte gaten onder deze omstandigheden een fout zijn. Als een van de uitstelvlaggen is ingeschakeld (fouten met getypte gaten omzetten in waarschuwingen), schakelt de vlag -fno-warn-typed-holes de waarschuwingen uit. Dit betekent dat compilatie stil slaagt en het evalueren van een hole een runtime-fout oplevert.

Semantiek van getypte gaten

Van de waarde van een typegat kan eenvoudig gezegd worden dat deze undefined is undefined , hoewel een getypt gat een compilatiefout veroorzaakt, dus het is niet strikt noodzakelijk om er een waarde aan toe te wijzen. Een getypt gat (wanneer deze is ingeschakeld) produceert echter een compilatietijdfout (of waarschuwing met uitgestelde typefouten) met de naam van het getypte gat, het afgeleide meest algemene type en de typen lokale bindingen. Bijvoorbeeld:

Prelude> \x -> _var + length (drop 1 x)

<interactive>:19:7: Warning:
    Found hole `_var' with type: Int
    Relevant bindings include
      x :: [a] (bound at <interactive>:19:2)
      it :: [a] -> Int (bound at <interactive>:19:1)
    In the first argument of `(+)', namely `_var'
    In the expression: _var + length (drop 1 x)
    In the expression: \ x -> _var + length (drop 1 x)

Merk op dat in het geval van getypte gaten in uitdrukkingen die zijn ingevoerd in de GHCi-repl (zoals hierboven), het type van de ingevoerde uitdrukking ook werd gerapporteerd, zoals it (hier van type [a] -> Int ).

Getypte gaten gebruiken om een klasse-instantie te definiëren

Getypte gaten kunnen het eenvoudiger maken om functies te definiëren via een interactief proces.

Stel dat u een klasse-instantie Foo Bar wilt definiëren (voor uw aangepaste Bar type, om het te gebruiken met een polymorfe bibliotheekfunctie waarvoor een Foo instantie vereist is). U zou nu traditioneel de documentatie van Foo opzoeken, erachter komen welke methoden u moet definiëren, hun typen onderzoeken enz. - maar met getypte gaten kunt u dat eigenlijk overslaan!

Definieer eerst een dummy-instantie:

instance Foo Bar where

De compiler zal nu klagen

Bar.hs:13:10: Warning:
No explicit implementation for
  ‘foom’ and ‘quun’
In the instance declaration for ‘Foo Bar’

Ok, dus we moeten foom definiëren voor Bar . Maar wat is dat zelfs zou moeten zijn? Nogmaals, we zijn te lui om in de documentatie te kijken en vragen de compiler:

instance Foo Bar where
  foom = _

Hier hebben we een getypt gat gebruikt als een eenvoudige "documentatiequery". De compiler voert uit

Bar.hs:14:10:
    Found hole ‘_’ with type: Bar -> Gronk Bar
    Relevant bindings include
      foom :: Bar -> Gronk Bar (bound at Foo.hs:4:28)
    In the expression: _
    In an equation for ‘foom’: foom = _
    In the instance declaration for ‘Foo Bar’

Merk op hoe de compiler de klasse type variabele al heeft gevuld met de betonnen type Bar waarvoor we deze willen instantiëren. Dit kan de handtekening een stuk eenvoudiger te begrijpen maken dan de polymorfe in de klassedocumentatie, vooral als je te maken hebt met een meer gecompliceerde methode, bijvoorbeeld een klasse met meerdere parameters.

Maar wat is Gronk godsnaam? Op dit moment is het waarschijnlijk een goed idee om Hayoo te vragen. Zonder dat kunnen we echter nog steeds wegkomen: als een blinde gok nemen we aan dat dit niet alleen een constructor van het type is, maar ook de constructor van een enkele waarde, dat wil zeggen dat het kan worden gebruikt als een functie die op een of andere manier een Gronk a waarde Gronk a . Dus we proberen het

instance Foo Bar where
  foom bar = _ Gronk

Als we geluk hebben, is Gronk eigenlijk een waarde, en de compiler zal nu zeggen

    Found hole ‘_’
      with type: (Int -> [(Int, b0)] -> Gronk b0) -> Gronk Bar
    Where: ‘b0’ is an ambiguous type variable

Ok, dat is lelijk - merk eerst op dat Gronk twee argumenten heeft, dus we kunnen onze poging verfijnen:

instance Foo Bar where
  foom bar = Gronk _ _

En dit is nu vrij duidelijk:

    Found hole ‘_’ with type: [(Int, Bar)]
    Relevant bindings include
      bar :: Bar (bound at Bar.hs:14:29)
      foom :: Bar -> Gronk Bar (bound at Foo.hs:15:24)
    In the second argument of ‘Gronk’, namely ‘_’
    In the expression: Gronk _ _
    In an equation for ‘foom’: foom bar = Gronk _ _

U kunt nu verdere vooruitgang, bijvoorbeeld door deconstructie van het bar -waarde (de componenten zullen dan opdagen, met types, in de Relevant bindings sectie). Vaak is het op een gegeven moment volkomen duidelijk wat de juiste definitie zal zijn, omdat je alle beschikbare argumenten ziet en de typen als een puzzel in elkaar passen. Of anders ziet u misschien dat de definitie onmogelijk is en waarom.

Dit alles werkt het beste in een editor met interactieve compilatie, bijvoorbeeld Emacs met haskell-modus. U kunt vervolgens getypte gaten gebruiken, net als muisaanwijzer-waardequery's in een IDE voor een geïnterpreteerde dynamische gebiedende taal, maar zonder alle beperkingen.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow