Haskell Language
Gedeeltelijke toepassing
Zoeken…
Opmerkingen
Laten we enkele misvattingen ophelderen die beginners kunnen maken.
Mogelijk hebt u functies aangetroffen zoals:
max :: (Ord a) => a -> a -> a
max m n
| m >= n = m
| otherwise = n
Beginners zien meestal max :: (Ord a) => a -> a -> a
als functie die twee argumenten (waarden) van type a
en een waarde van type a
retourneert. Wat er echter echt gebeurt, is dat max
een argument van type a
en een functie van type a -> a
retourneert a -> a
. Deze functie neemt vervolgens een argument van type a
en retourneert een uiteindelijke waarde van type a
.
max
kan inderdaad worden geschreven als max :: (Ord a) => a -> (a -> a)
Overweeg de typeaanduiding van max
:
Prelude> :t max
max :: Ord a => a -> a -> a
Prelude> :t (max 75)
(max 75) :: (Num a, Ord a) => a -> a
Prelude> :t (max "Fury Road")
(max "Fury Road") :: [Char] -> [Char]
Prelude> :t (max "Fury Road" "Furiosa")
(max "Fury Road" "Furiosa") :: [Char]
max 75
en max "Fury Road"
misschien niet uit als functies, maar in werkelijkheid wel.
De verwarring komt voort uit het feit dat we in de wiskunde en vele andere gangbare programmeertalen functies mogen hebben die meerdere argumenten aannemen. In Haskell kunnen functies echter maar één argument aannemen en kunnen ze waarden als a
of functies zoals a -> a
retourneren.
Gedeeltelijk toegepaste toevoegingsfunctie
We kunnen de gedeeltelijke toepassing gebruiken om het eerste argument te "vergrendelen". Na het toepassen van één argument blijven we achter met een functie die nog een argument verwacht voordat het resultaat wordt geretourneerd.
(+) :: Int -> Int -> Int
addOne :: Int -> Int
addOne = (+) 1
We kunnen vervolgens addOne
gebruiken om er een aan een Int
toe te voegen.
> addOne 5
6
> map addOne [1,2,3]
[2,3,4]
Een gedeeltelijk toegepaste functie retourneren
Het teruggeven van gedeeltelijk toegepaste functies is een techniek om beknopte code te schrijven.
add :: Int -> Int -> Int
add x = (+x)
add 5 2
In dit voorbeeld is (+ x) een gedeeltelijk toegepaste functie. Merk op dat de tweede parameter voor de functie toevoegen niet hoeft te worden opgegeven in de functiedefinitie.
Het resultaat van het aanroepen van add 5 2
is zeven.
secties
Secties zijn een beknopte manier om argumenten gedeeltelijk toe te passen op infix-operators.
Als we bijvoorbeeld een functie willen schrijven die "ing" aan het einde van een woord toevoegt, kunnen we een sectie gebruiken om een functie bondig te definiëren.
> (++ "ing") "laugh"
"laughing"
Merk op hoe we het tweede argument gedeeltelijk hebben toegepast. Normaal gesproken kunnen we de argumenten slechts gedeeltelijk in de opgegeven volgorde toepassen.
We kunnen ook de linker sectie gebruiken om het eerste argument gedeeltelijk toe te passen.
> ("re" ++) "do"
"redo"
We zouden dit ook kunnen schrijven met een normale prefix gedeeltelijke toepassing:
> ((++) "re") "do"
"redo"
Een opmerking over aftrekken
Beginners vaak ten onrechte sectie ontkenning.
> map (-1) [1,2,3]
***error: Could not deduce...
Dit werkt niet omdat -1
wordt ontleed als de letterlijke -1
plaats van de gesegmenteerde operator -
toegepast op 1
. De functie voor subtract
bestaat om dit probleem te omzeilen.
> map (subtract 1) [1,2,3]
[0,1,2]