🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.funkcyjne
Article #188

Re: leniwosc jezyka

#188
From: Michal Przybylek
Date: Sun, 19 Jan 2003 16:21
168 lines
5096 bytes
"Lucifer" <przemek@nospam.pa55.bytom.sdi.tpnet.pl> wrote:

> > Leniwosc polega na tym, ze dana czynnosc jest wykonywana dopiero wtedy,
> > kiedy jej wykonanie jest niezbedne.
>
> Czyli odkladanie zadan jak dlugo to mozliwe?

Tak (koncepcyjnie).

> Czyli leniwe podejscie moze byc co najwyzej tak samo zlozone(powolne) co
>   gorliwe?

Tak.


> Przypuscmy, ze jestem funkcja :) i zalkladam ze jest tak jak piszesz i
> dochodze do wniosku, ze musze zbadac, czy otrzymany argument jest tym co
> chce czy jest thunkiem - wtedy musze go uruchomic.
>
> Ok, co w takim razie znaczy IO w deklaracjach funkcji? Powyzsze jakos
> nie bardzo pasuje do we/wy (co zauwazylem). IO zapobiega leniwosci?

Chyba nie rozumiem. Dla IO wazne sa tylko dwie rzeczy - a) aby wszystkie IO
zostaly wykonane przed zakonczeniem dzialania programu i b) aby byly
wykonane w zadanej kolejnosci.

IO sa zbudowane w ten sposob, ze pod nimi jest ukryty obecny stan. Stan ten
jest przekazywany *sekwnecyjie* wzdluz poszczegolnycha akcji.


> > Leniwe podejscicie umozliwia troche inne spojrzenie na konstrukcje
> > programow. Jest jakgdyby rozciagniecieciem rekurencji na dane inne niz
> > funkcje (1) i uogulnieniem jej przy pracy z funkcjami (2), przez co
> > doskonale wpasowuje sie do wiadomego stylu programowania [zreszta,
> > nie do konca... (3)].
>
> Mozna jakis przyklad?


1.

ones = 1:ones

[
    ones 0 = 1
    ones n = ones (n-1)
]


even = 0:[n+1 | n <- odd]
odd  = 1:[n+1 | n <- tail even]

[
    even 0 = 0
    even n = odd (n-1) + 1

    odd 0 = 1
    odd n = even n + 1
]


fact = 1:[a*n | (a, n) <- zip fact [1..]]

fib = 0:1:[a+b | (a, b) <- zip fib (tail fib)]

[
    w rzeczywistosci konstrukcja przebiega jakgdyby od drugiej strony,
    czyli:

    fact a = local 0  where
      local 0 = 1
      local n | (n == a) = n        -- zakonczenie rekurencji
              | otherwise = n * local (n+1)
]



2.

-- chyba najbardziej znany kombinator :-)
-- znajduje punkt staly funkcji
y f = f (y f)

-- silnia z ukryta rekurencja
fact = y (\f n -> if n == 0 then 1 else n * f (n-1))



Jak to dziala ?

niech r = \f n -> if n == 0 then 1 else n * f (n-1)

i

fixr jest punktem stalym tej funkcji

mamy:

fixr = r fixr

stad:

fixr = \n -> if n == 0 then 1 else n * fixr (n-1)

co oczywiscie jest silnia.


3. Nie zawsze chcemy aby dana struktora byla w ogole tworzona.

Spojrzen na iteracje jest wiele. Rekurencja ogonkowa dla podejscia
funkcyjnego jest mniej wiecej na poziomie `goto' z jezykow imperatywnych.
Oczywiscie chcielibysmy sie poruszac na duzo wyzszym poziomie abstrakcji
takze w obrebie tego paradygmatu.

Najprostszym rozwiazaniem tutaj jest konstrukcja leniwych list (zobacz punkt
1) i odpowiednie ich obrabianie.

Np.:

fFact n = fact !! n

fFib n = fib !! n


lub za pomoca dostarczanych narzedzi (podstawowe to fold i unfold [*]):

fact n = foldl (*) 1 [1..n]

fib n = fst (unfoldInf (0, 1) (\(a, b) -> (b, b+a)) !! n)


W ten sposob mozna zapisywac niemal kazdy iteracyjny algorytm. Problemem w
tym podejsciu jest wlasnie sama leniwosc. Leniwosc wymusza spamietywanie.
Tymczasem my oczekujemy, ze powyzsze funkcje beda wykonywaly sie w O(1) [**]
pamieci i O(n) czasie.

Rozwiazaniem (oczywiscie w Haskell'u nieodpowiednim) moglo by byc stworzenie
struktory, konwertowalnej w razie potrzeby na liste i obliczajacej zawsze od
poczatku wszystkie elementy.


Eh, szkoda, ze w "prawdziwych" jezykach funkcyjnych tak sie nie pisze...


> > Oczywiscie leniwosc ma sens tylko w jezykach czystych.
>
> Tzn? Czym sa czyste jezyki?

Nie umozliwiajace side-effect'ow.


[*]

`unfoldInf' to zwykly unfold bez warunku koncowego:

unfoldInf init f = init:(unfoldInf (f init) f)


[**]

Nie znam na tyle dobrze implementacji Haskell'a, aby powiedziec, czy
powyzsze przyklady wykonaja sie w O(1) pamieci (calkiem mozliwe, ze tak).
Jest to jednak bez znaczenia. W ogolnym przypadku tak nie bedie i na pewno
nie mozna na tym polegac (pozatym jak juz mowilem jest to niezgodne z
leniwoscia i nieintuicyjne).


mp
Technical Details
Message-ID: <b0ejh4$k69$1@news.tpi.pl>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!news.ipartners.pl!newsfeed.gazeta.pl!newsfeed.tpinternet.pl!news.tpi.pl!not-for-mail
References: <b0a9ea$aum$1@news.tpi.pl> <b0bifd$on$1@news.tpi.pl> <b0bs67$4tl$1@news.tpi.pl>

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!news.ipartners.pl!newsfeed.gazeta.pl!newsfeed.tpinternet.pl!news.tpi.pl!not-for-mail
From: "Michal Przybylek" <pkmichal@poczta.onet.pl>
Newsgroups: pl.comp.lang.funkcyjne
Subject: Re: leniwosc jezyka
Date: Sun, 19 Jan 2003 17:21:11 +0100
Organization: tp.internet - http://www.tpi.pl/
Lines: 170
Message-ID: <b0ejh4$k69$1@news.tpi.pl>
References: <b0a9ea$aum$1@news.tpi.pl> <b0bifd$on$1@news.tpi.pl> <b0bs67$4tl$1@news.tpi.pl>
NNTP-Posting-Host: 62.244.143.45
X-Trace: news.tpi.pl 1042993509 20681 62.244.143.45 (19 Jan 2003 16:25:09 GMT)
X-Complaints-To: usenet@tpi.pl
NNTP-Posting-Date: Sun, 19 Jan 2003 16:25:09 +0000 (UTC)
X-Newsreader: Microsoft Outlook Express 6.00.2600.0000
X-MSMail-Priority: Normal
X-Priority: 3
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit