Mit Haskell können Sie keine vorhandenen Variablen ändern. Es erlaubt Ihnen jedoch, Variablennamen wiederzuverwenden, und das ist alles, was hier passiert. Eine Möglichkeit, dies zu sehen ist GHCi zu stellen, mit der :i[nfo]
Richtlinie, in dem die Variable deklariert wurde:
Prelude> let a = 1
Prelude> :i a
a :: Num a => a -- Defined at <interactive>:2:5
Prelude> let a = 2
Prelude> :i a
a :: Num a => a -- Defined at <interactive>:4:5
Diese sind eigentlich zwei ganz getrennte, verschiedene Variablen, die nur der gleiche Name genannt werden passieren! Wenn Sie nur für a
fragen, wird die neuere Definition sein “ ” bevorzugt, aber die alte ist immer noch da – eine Möglichkeit, dies zu sehen, wie Chi in den Kommentaren bemerkt, ist a
in einer Funktion zu verwenden:
Prelude> let a = 2
Prelude> :i a
a :: Num a => a -- Defined at <interactive>:4:5
Prelude> let f x = a + x
Prelude> let a = 3
Prelude> f (-2)
0
f
muss nie darauf achten, dass Sie eine neue Variable definiert haben, die auch a
heißt; aus seiner Sicht a
war eine unveränderliche Variable, die immer so bleibt wie sie ist.
Es lohnt sich, ein wenig darüber zu sprechen, warum GHCi die spätere Definition bevorzugt. Dies geschieht nicht sonst in Haskell Code passieren; wenn Sie insbesondere versuchen, das folgende Modul zu kompilieren, gibt es einfach einen Fehler in Bezug auf doppelte Definition:
a = 1
a = 2
main :: IO()
main = print a
Der Grund, dass so etwas in GHCi erlaubt ist, ist, dass es von Haskell-Modulen unterschiedliche arbeitet. Die Sequenz von GHCi-Befehlen bildet tatsächlich eine Sequenz von Aktionen in der IO-Monade& dagger;; dh das Programm würde
main :: IO()
main = do
let a = 1
let a = 2
print a
Jetzt sein, wenn Sie über Monaden gelernt haben, wissen Sie, dass dies für
main =
let a = 1 in (let a = 2 in (print a))
nur syntaktischer Zucker ist und das ist wirklich der entscheidende Bit dafür, warum Sie können den Namen a
wiederverwenden: der zweite, a = 2
, lebt in einem engeren Bereich als der erste. Es ist also lokaler und lokale Definitionen haben Priorität.Ob das eine gute Idee ist, ist ein wenig umstritten; ein gutes Argument dafür ist, dass Sie eine Funktion wie
greet :: String -> IO()
greet name = putStrLn $ "Hello, "++name++"!"
und es gerade arbeiten, werden nicht aufhören können, weil jemand anderer Stelle
Neben
name :: Car -> String
name car | rollsOverAtRightTurn car = "Reliant Robin"
| fuelConsumption car > 50*litrePer100km
= "Hummer"
| ... = ...
definiert, es ist wirklich sehr nützlich, dass man “ neu definieren ” Variablen während herumalbern in GHCi, auch wenn es nicht ist so eine gute Idee, Sachen in einem richtigen Programm neu zu definieren, das konsistentes Verhalten zeigen soll.
& dolch; Wie Dfeuer bemerkt, ist dies nicht die ganze Wahrheit. Sie können einige Dinge in GHCi tun, die in einem IO
Do-Block nicht erlaubt sind, insbesondere können Sie data
Typen definieren und class
es. Aber jede normale Aussage oder variable Definition wirkt sozusagen in der IO
Monade.
das funktioniert nicht in meinem ... – Netwave
Versuchen Sie, 'a = 1; a = 2' innerhalb einer '.hs' Datei und kompiliere sie mit' ghc' ... – Bakuriu
GHCi Befehle sind IO-Aktionen, also ist es so, als ob alles, was du tippst, in einem 'do'-Block liegt. Das bedeutet, dass die nachfolgende Zuweisung an denselben Namen wie verschachtelt ist. Lass uns die alte Bindung * shadow *. – Bakuriu