To jedna z trudnych drobiazgów, które mnie zdezorientowały, kiedy po raz pierwszy spróbowałem Haskella. Nie rozumiesz znaczenia konstrukcji <-
w notacji do-notacji. result <- f handle
nie oznacza "przypisanie wartości f handle
do result
"; oznacza to "wiążę result
z wartością" wyodrębnioną "z monadycznej wartości f handle
" (gdzie "ekstrakcja" dzieje się w jakiś sposób, który jest określony przez konkretną instancję Monady, której używasz, w tym przypadku monotonię IO).
Tj jakiegoś Monad typeclass m, oświadczenie <-
bierze wyrażenie typu m a
na prawej stronie i zmienną typu a
na lewej stronie, i wiąże zmienną na wartość. Tak więc w twoim konkretnym przykładzie, z result <- f handle
, mamy typy f result :: IO a
, result :: a
i return result :: IO a
.
PS do-notation ma również specjalną formę let
(bez słowa kluczowego in
w tym przypadku!), Która działa jako czysty odpowiednik <-
. Więc można było przepisać swój przykład jako:
withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a
withFile' path mode f = do
handle <- openFile path mode
let result = f handle
hClose handle
result
W tym przypadku, ponieważ let
to proste zadanie, rodzaj result
jest IO a
.
Oh d'oh! Zupełnie brakowało operatora "ssania" '<-'! – drozzy
Czy może to być również 'niech result = f uchwyt; hZamknij uchwyt; wynik "czy też znowu nie rozumiem monady? – delnan
@delnan to 'do {handle <- ścieżka trybu openFile; hZamknij uchwyt; f uchwyt; } ', więc' f uchwyt 'prawdopodobnie narzekałby na zamknięty uchwyt. –