Sök…


Bang-mönster

Mönster som är annoterade med ett bang ( ! ) Utvärderas strikt istället för lata.

foo (!x, y) !z = [x, y, z] 

I det här exemplet utvärderas båda x och z till svag huvudformell form innan listan returneras. Det motsvarar:

foo (x, y) z = x `seq` z `seq` [x, y, z]

Bang-mönster aktiveras med hjälp av BangPatterns Haskell 2010 BangPatterns .

Normala former

Detta exempel ger en kort översikt - för en mer djupgående förklaring av normala former och exempel, se denna fråga .

Minskad normal form

Den minskade normala formen (eller bara normal form, när sammanhanget är klart) för ett uttryck är resultatet av utvärdering av alla reducerbara subexpressions i det givna uttrycket. På grund av den icke-strikta semantiken för Haskell (vanligtvis kallad latskap ) kan en subexpression inte reduceras om den är under ett bindemedel (dvs. en lambda-abstraktion - \x -> .. ). Den normala formen för ett uttryck har den egenskapen att om det finns är det unikt.

Med andra ord, det spelar ingen roll (i termer av denotational semantik) i vilken ordning du minskar subexpressions. Men nyckeln till att skriva performanta Haskell-program är ofta att säkerställa att rätt uttryck utvärderas vid rätt tidpunkt, dvs förståelsen av den operativa semantiken.

Ett uttryck vars normala form själva sägs vara i normal form .

Vissa uttryck, t.ex. let x = 1:x in x , har ingen normal form, men är fortfarande produktiva. Exempeluttrycket har fortfarande ett värde , om man medger oändliga värden, som här är listan [1,1, ...] . Andra uttryck, som let y = 1+y in y , har inget värde, eller deras värde är undefined .

Svag huvud normal form

De RNF motsvarar fullt utvärdera ett uttryck - likaså, den svaga huvudet normalform (WHNF) motsvarar utvärdera till huvudet av uttrycket. Huvudet för ett uttryck e utvärderas fullständigt om e är en applikation Con e1 e2 .. en och Con är en konstruktör; eller en abstraktion \x -> e1 ; eller en partiell applikation f e1 e2 .. en , där partiell applikation betyder att f tar mer än n argument (eller på motsvarande sätt är typen av e en funktionstyp). I vilket fall som helst kan subexpressions e1..en utvärderas eller utvärderas för att uttrycket ska vara i WHNF - de kan till och med undefined .

Utvärderingssemantiken för Haskell kan beskrivas i termer av WHNF - för att utvärdera ett uttryck e , först utvärdera det till WHNF och sedan rekursivt utvärdera alla dess underuttryck från vänster till höger.

Den primitiva seq funktionen används för att utvärdera ett uttryck för WHNF. seq xy är denotationellt lika med y (värdet på seq xy är exakt y ); vidare utvärderas x till WHNF när y utvärderas till WHNF. Ett uttryck kan också utvärderas till WHNF med ett bangmönster (aktiverat av förlängningen -XBangPatterns ), vars syntax är som följer:

f !x y = ... 

I vilken x kommer att utvärderas till WHNF när f utvärderas, medan y inte (nödvändigtvis) utvärderas. Ett bangmönster kan också visas i en konstruktör, t.ex.

data X = Con A !B C .. N

i vilket fall sägs konstruktören Con vara strikt i B fältet, vilket innebär att B fältet utvärderas till WHNF när konstruktören appliceras på tillräckliga (här, två) argument.

Lata mönster

Lata eller oåterkalleliga mönster (betecknade med syntaxen ~pat ) är mönster som alltid matchar, utan att ens se på det matchade värdet. Detta betyder att lata mönster matchar jämna bottenvärden. Emellertid kommer efterföljande användningar av variabler bundna i undermönster i ett oåterkalleligt mönster att tvinga mönstermatchningen att ske, utvärdera till botten om inte matchen lyckas.

Följande funktion är lat i sitt argument:

f1 :: Either e Int -> Int
f1 ~(Right 1) = 42

och så får vi

λ» f1 (Right 1)
42
λ» f1 (Right 2)
42
λ» f1 (Left "foo")
42
λ» f1 (error "oops!")
42
λ» f1 "oops!"
*** type mismatch ***

Följande funktion är skriven med ett lat mönster men använder i själva verket mönsterets variabel som tvingar matchen, så kommer att misslyckas för Left :

f2 :: Either e Int -> Int
f2 ~(Right x) = x + 1

λ» f2 (Right 1)
2
λ» f2 (Right 2)
3
λ» f2 (Right (error "oops!"))
*** Exception: oops!
λ» f2 (Left "foo")
*** Exception: lazypat.hs:5:1-21: Irrefutable pattern failed for pattern (Right x)
λ» f2 (error "oops!")
*** Exception: oops! 

let bindningar är lata, uppför sig som oåterkalleliga mönster:

act1 :: IO ()
act1 = do
    ss <- readLn
    let [s1, s2] = ss :: [String]
    putStrLn "Done"

act2 :: IO ()
act2 = do
    ss <- readLn
    let [s1, s2] = ss
    putStrLn s1

Här act1 arbeten på insatser som parse någon lista med strängar, medan act2 den putStrLn s1 behov värdet av s1 vilka krafter mönstermatchning för [s1, s2] , så det fungerar bara för listor över exakt två strängar:

λ» act1
> ["foo"]
Done
λ» act2
> ["foo"]
*** readIO: no parse ***

Stränga fält

I en data förklaring prefix en typ med en smäll ( ! ) Gör området en strikt fält. När datakonstruktören tillämpas kommer dessa fält att utvärderas till svag huvud normalform, så att data i fälten garanteras alltid att vara i svagt huvud normal form.

Stränga fält kan användas i både inspelnings- och icke-inspelningstyper:

data User = User
    { identifier :: !Int
    , firstName :: !Text
    , lastName :: !Text
    }

data T = MkT !Int !Int


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow