2011-12-19 9 views
5

uygulanan Nasıl:withFile yazar <strong>withFile</strong> yöntemin aşağıdaki uygulamasını sağlar, Haskell bir <a href="http://learnyouahaskell.com/input-and-output#files-and-streams">haskell tutorial</a> ardından

withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a 
withFile' path mode f = do 
    handle <- openFile path mode 
    result <- f handle 
    hClose handle 
    return result 

Ama neden bir return içinde result sarmak gerekiyor? Sağlanan işlev f zatentüründe olduğu gibi Handle -> IO a türünde görülebilir mi?

cevap

7

Haklısınız: işlev böyle yazılmıştır eğer öyleyse f zaten bir IO verir:

withFile' path mode f = do 
    handle <- openFile path mode 
    f handle 

dönüş gerek olmazdı. Sorun hClose handle arasındaki gelir, bu nedenle ilk sonucu depolamak zorunda:

result <- f handle 

ve <- yapıyor IO kurtulur. Yani return onu geri koyar.

+0

Oh d'oh! Tamamen _sucking_ '<-' operatörünü kaçırdı! – drozzy

+1

Ayrıca 'sonuç = f tutabilirsiniz; hClose kolu; sonuç ya da tekrar monad anlayışını bozmadım mı? – delnan

+3

@delnan, {handle <- openFile modu yolu; hClose kolu; f kolu; } ', yani' f tutamaç 'muhtemelen kapalı bir sap hakkında şikâyet ederdi. –

3

Bu, Haskell'i ilk denediğimde beni şaşırtan zor küçük şeylerden biridir. Açıklamada <- yapısının anlamını yanlış anlıyorsunuz. result <- f handle "f handle değerini result olarak atama" anlamına gelmez; "f handle monadik değerinden" ayıklanan "değerine" result10 "bağlamanız gerekir (burada" ayıklama ", kullandığınız belirli Monad örneğiyle tanımlanan bir şekilde gerçekleşir, bu durumda IO monad).

yanı, bir Monad typeclass m, <- ifadesi sağından tip m a bir ifade ile sol taraftaki tip a bir değişken alan ve bir değere değişken bağlanır. Böylece, örneğinizde, result <- f handle ile f result :: IO a, result :: a ve return result :: IO a türlerine sahibiz.

PS do-notation, <-'a tam bir karşılık olarak çalışan let (bu durumda in anahtar sözcüğü olmadan) özel bir biçime sahiptir. Yani olarak örnek yazabilirsiniz: let basit atama, çünkü bu durumda

withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a 
withFile' path mode f = do 
    handle <- openFile path mode 
    let result = f handle 
    hClose handle 
    result 

, result tipi IO a olduğunu.

+1

Serin! Ben rhs :-) değerini emmek gibi, <-'emmek operatörü çağırmak – drozzy