Vaje#
Naloga 1#
Napišite prestreznik
mute
, ki prestreže vgrajeniPrint
in prepreči izpis. Program naj nadaljuje nemoteno.Napišite prestreznik
shift_text_right n
, ki vse izpisano besedilo zamakne v desno zan
mest.Prestreznik
underline
vsako izpisano vrstico podčrta (tako da v novi vrstici izpiše primerno število znakov-
).Prestreznik
custom_separator sep
naj poskrbi, da se ločeno izpisani tekst ne loči z\n
temveč separatorjemsep
.Napišite prestreznik
counter limit
, ki šteje izpise in vrne rezultat, samo, če je bilo izpisanih manj kotlimit
znakov. Če je bilo izpisanih več, naj vrneNone
.Popravite zgornje prestreznike, da bodo ponovno sprožili učinke
Print
, ki ga bo ujel limitni prestreznik.
Naloga 2#
Napišite učinka
Get : unit -> int
inPut : int -> unit
in program, ki ju smiselno uporablja.Napišite prestreznik
state
, ki program ustrezno implementira učinkaGet
inPut
v monadični obliki - izračun pretvori v funkcijo, ki sprejme začetno vrednost stanja in vrne rezultat.
Naloga 3#
Vzemi drevo, ki ga definira naslednji tip:
type 'a tree
= Empty
| Node of tree * 'a * tree
type direction = Left | Right
in učinek Pick : unit -> direction
.
Napišite funkcijo
explore : int tree -> int
, ki raziskuje drevo in podatke združuje s pomočjo globalne funkcijeop : 'a -> int -> 'a
. Raziskovanje praznega drevesa naj vrne0
, raziskovanje nepraznega pa naj najprej izvede učinekPick
in glede na rezultat izbere levo ali desno poddrevo, nadaljuje raziskovanje tega poddrevesa in vrne rezultat združen z vrednostjo v korenu.Napišite prestreznike in pripadajočo funkcijo
op
, ki glede na funkcijoexplore
vrnejo naslednje rezultate:Vrednost minimalne poti v drevesu
Vrednost maksimalne poti v drevesu
Število vseh poti v drevesu
Vrednosti vseh poti v drevesu
Povprečno vrednost poti v drevesu
Naloga 4#
Želimo narediti prestreznik za memoizacijo. Že izračunane vrednosti bomo (neučinkovito) hranili v seznamu parov.
Napišite funkciji za delo s seznami parov
find : 'a -> ('a * 'b) list -> 'b option
insave : 'a -> 'b -> ('a * 'b) list -> ('a * 'b) list
.Da si poenostavimo življenje, se osredotočimo zgolj na funkcije
int -> int
. V nadaljevanju uporabljamo preimenovanjitype arg = int
intype result = int
. Naša memoizacija bo potrebovala pomnilnik, zato bomo zanj definirali poseben prestreznik. Definirajte učinkaLookup : arg -> result option
inRemember : arg * result -> unit
. Nato zanju napišite prestreznikmemory
, ki upravlja s pomnilnikom tipa(arg * result) list
.Sedaj lahko funkcije že uporabljajo pomnilnik za memoizacijo, vendar bi želeli, da je memoizacija funkcije zgolj eno od možnih izvajanj. Zato definirajte učinek
Evaluate : ((int -> int) * int) -> int
, ki sprejme funkcijo in argument, ter nam vrne rezultat. Funkcij sedaj ne kličemo več kotf x
temveč kotperform (Evaluate (f, x))
(priporočam, da si ustvarite pomožno funkcijoeval f x = ...
za lepšo sintakso). Napišite prestreznikno_memo
, ki funkcijo izvede, kot bi se izvedla sicer. Nato napišite še prestreznikmemo
, ki funkcijo memoizira.
Namig: Če želite rekurzivne prestreznike, jih definirajte kot let rec h () = handler ...
kjer jih lahko sedaj v telesu definicije uporabite z with h () handle ...
.
Naloga 5#
Generatorji so funkcije, ki zaporedoma uporabljajo učinek Yield : int -> unit
.
Napišite funkcijo, ki generira vsa naravna števila.
Napišite funkcijo
collect n gen
, ki iz generatorjagen
pobere prvihn
vrednosti.Napišite prestreznik
generator gen
, ki na zahtevoGenerate : unit -> int
generira novo vrednost iz generatorjagen
.
Namig: Eden od možnih načinov je, da z dodatnim prestreznikom generatorje iz tipa unit -> unit!{Yield}
pretvorite v tip unit -> gen
. Tu je gen
novo definiran tip, ki označuje, da je generator bodisi končal, bodisi pa je proizvedel element in svoje posodobljeno stanje (ponovno tipa unit -> gen
). Če potrebujete, ima Eff vgrajeno funkcijo failwith msg
.