2015-12-10 7 views
7

Mentre l'hacking Catasta, ho trovato this:C'è davvero un motivo di scoppio sull'unità?

!() <- atomicModifyIORef (eoExeCache eo) $ \m' -> 
    (Map.insert name epath m',()) 

HLint dice: “togliere quella cosa”. Ma non penso che sia un errore di battitura. C'è qualche ragione per scrivere mai !()?

+3

Poiché '()' è già nella forma normale (e, quindi, in WHNF), non penso che ci sia un punto nell'utilizzo di un modello di scoppio, qui. – Jubobs

+1

Un botto prima di un modello di costruzione non ha senso - stiamo forzando comunque il valore. – chi

+2

Alcune indagini sul repository rivelano che questo modello bang è stato introdotto da Michael Snoyman in [questo commit] (https://github.com/commercialhaskell/stack/commit/5039c19655f496926fa882c93efe2867afb97468). Forse dovresti pubblicare la tua domanda nel tracker dei problemi del repository e chiedergli cosa stava pensando al momento di scriverlo. Michael conosce le sue cose, quindi direi che ha semplicemente lasciato questo superfluo botto in una svista. – Jubobs

risposta

6

In caso di dubbio (e non di fretta) consultare lo specification.

L'espressione

do !() <- foo 
    bar 

desugars a

let ok !() = bar 
    ok _ = fail .. 
in foo >>= ok 

A rules for function definition questo equivale a

let ok = \x -> case x of !() -> bar 
         _ -> fail ... 
in foo >>= ok 

Ora la rules for bang patterns sono nel manuale d'uso GHC, perché non è haskell standard. ci troviamo che possiamo riscrivere questo in

let ok = \x -> x `seq` (case x of() -> bar 
            _ -> fail ...) 
in foo >>= ok 

Ora seq is defined in termini di suo argomento essere ⊥ oppure no. Quindi, x è ⊥, ma il secondo argomento a seq, ovvero lo case x of ... è anche ⊥ in base allo semantics of pattern matching. O x non è ⊥ e seq equivale al suo secondo argomento. In entrambi i casi, il codice è identico a

let ok = \x -> case x of() -> bar 
         _ -> fail ... 
in foo >>= ok 

che, ripercorrendo questi passaggi, è equivalente a

do() <- foo 
    bar 

In conclusione: Non v'è alcun motivo per farlo in un'espressione do.

V'è, tuttavia, una differenza tra

let() = foo 
in bar 

(dove sarà mai essere valutati foo) e

let !() = foo 
in bar 

perché let-espressioni hanno disposizioni speciali nel semantics for bang patterns.