# Funkcyjne
## Lista 2
### z1
```ocaml
let my_length = List.fold_left (fun acc _ -> acc + 1) 0
let my_rev = List.fold_left (fun acc x -> x :: acc) []
let my_map f xs = List.fold.right (fun x acc -> f x :: acc) xs []
let my_filter f xs = List.fold_right (fun x acc -> if f x then x :: acc else acc) xs []
let my_rev_map f = List.fold_left (fun acc x -> (f x) :: acc) []
```
### z2
```ocaml
let rec sublists = function
| [] -> [[]]
| x::xs -> let ls = sublists xs in
List.map (fun l -> x::l) ls @ ls;;
#### v2
let rec sublists xs = match xs with
| [] -> []
| x :: [] -> [[x]; []]
| x :: xs -> let ys = sublists(xs)
in List.fold_left (fun acc y -> (x :: y) :: acc) ys ys
```
### z3
```ocaml
let rec sufiks xs = match xs with
| [] -> []
| x :: [] -> [[x]; []]
| x :: ys -> xs :: sufiks ys
let prefiks lista = sufiks (List.rev lista);;
let rec prefix xs = match xs with
| [] -> []
| x :: [] -> [[]; [x]]
| x :: ys -> [] :: List.map (fun y -> x :: y ) (prefix ys)
```
### z4
```ocaml
:::spoiler nieważne
let rec insert cmp x xs = match xs with
| [] -> [x]
| y :: ls -> if cmp x y then x :: xs
else y :: insert cmp x ls
let stupid_merge cmp xs ys = List.fold_left (fun ls x -> insert cmp x ls) ys xs
:::
# nieogonowe
let rec merge cmp l1 l2 = match (l1, l2) with
| [], a -> a
| a, [] -> a
| x :: xs, y :: ys ->
if cmp x y then x :: merge cmp xs l2
else y :: merge cmp ys l1
else y :: merge cmp ys (x :: xs)
# ogonowe z odwracaniem
let merge_tail cmp lista1 lista2 =
let rec _merge cmp l1 l2 result =
match l1, l2 with
| [] , [] -> result
| [] , h :: t | h :: t , [] -> _merge cmp [] t (h::result)
| h1 :: t1 , h2 :: t2 -> if (cmp h1 h2)
then _merge cmp t1 l2 (h1::result)
else _merge cmp l1 t2 (h2::result)
in List.rev(_merge cmp lista1 lista2 []);;
let rec halve ls = match ls with
| [] -> [[]; []]
| a :: [] -> [[a]; []]
| a :: b :: ys -> let xs = halve ys in
[(a :: List.hd xs); (b :: List.hd(List.tl xs))];;
let rec mergesort ls = match ls with
| [] -> []
| [a] -> [a]
| _ -> let xs = halve ls in
merge (mergesort (List.hd xs)) (mergesort (List.hd (List.tl xs)));;
:::spoiler kornelia
let rec mergesort cmp xs = match xs with
| [] -> []
| [x] -> [x]
| xs -> let [ys;zs] = halve xs in merge cmp (mergesort cmp ys) (mergesort cmp zs)
:::
porownyywanie czasu
let time f x =
let t = Sys.time() in
let fx = f x in
Printf.printf "Execution time: %fs\n" (Sys.time() -. t);
fx
pd : time merge_tail (<=) [1;2;5;7;8] [3;4;7;10]
```
### z5
```ocaml=
let merge_tail cmp reversed lista1 lista2 =
let rec _merge cmp l1 l2 result =
match l1, l2 with
| [] , [] -> result
| [] , h :: t | h :: t , [] -> _merge cmp [] t (h::result)
| h1 :: t1 , h2 :: t2 -> if (cmp h1 h2) == reversed
then _merge cmp l1 t2 (h2::result)
else _merge cmp t1 l2 (h1::result)
in _merge cmp lista1 lista2 [];;
----------------
let merge_tail cmp lista1 lista2 =
let rec _merge cmp l1 l2 result =
match l1, l2 with
| [] , [] -> result
| [] , h :: t | h :: t , [] -> _merge cmp [] t (h::result)
| h1 :: t1 , h2 :: t2 -> if (cmp h1 h2)
then _merge cmp l1 t2 (h2::result)
else _merge cmp t1 l2 (h1::result)
in _merge cmp lista1 lista2 [];;
let rec mergesort cmp xs = match xs with
| [] -> []
| [x] -> [x]
| _ -> let [ys;zs] = halve xs in merge_tail cmp (mergesort (fun a b -> not (cmp a b)) ys) (mergesort (fun a b -> not (cmp a b)) zs)
```
### z6
```ocaml
let rec insert x lst =
match lst with
| [] -> [[x]]
| h::t ->
(x::lst) :: (List.map (fun el -> h::el) (insert x t));;
let rec perm lst =
match lst with
| [] -> [lst]
| h::t ->
List.flatten (List.map (insert h) (perm t));;
```
::: spoiler Kornelia
```ocaml
(* przez wstawianie *)
let rec insert_everywhere xs y = match xs with
| [] -> [[y]]
| x :: xs -> (y :: x :: xs) :: List.map (fun z -> x :: z) (insert_everywhere xs y)
let rec perms xs = match xs with
| [] -> []
| x :: [] -> [[x]]
| x :: xs -> let ys = perms xs in List.flatten (List.map (fun s -> insert_everywhere s x) ys)
(* przez wybór *)
let rec perms2 ls =
let join x xs = match xs with
| [] -> [[x]]
| _ -> List.map (fun ys -> x :: ys) xs
in let rec inner ys acc = match ys with
| [] -> []
| [y] -> join y (perms2 acc)
| y :: ys -> let zs = perms2 (acc@ys) in (join y zs) @ (inner ys (y :: acc))
in inner ls []
```
:::
### z7
```ocaml
type ltree =
| Leaf
| Node of ltree * int * int * ltree
let make lt1 lt2 v = match lt1, lt2 with
| Leaf, Leaf -> Node (lt1, v, 1, lt2)
| Node (_, _, d1, _), Node (_, _, d2, _) -> if d2 < d1 then Node (lt1, v, d2 + 1, lt2) else Node (lt2, v, d1 + 1, lt1)
| Leaf, Node (_, _, d, _) -> Node (lt2, v, d + 1, lt1)
| Node (_, _, d, _), Leaf -> Node (lt1, v, d + 1, lt2)
let deep lt = match lt with
| Leaf -> 0
| Node(_, _, d, _) -> d
let rec join lt1 lt2 = match lt1, lt2 with
| Leaf, _ -> lt2
| _, Leaf -> lt1
| Node (l1, v1, d1, r1), Node (l2, v2, d2, r2) -> if v2 < v1 then let lt_new = join r2 lt1
in if deep lt_new > deep l2 then Node (lt_new, v2, d1 + 1, l2)
else Node (l2, v2, deep lt_new + 1, lt_new)
else join lt2 lt1
let add v lt = join lt (make Leaf Leaf v)
let del_min lt = match lt with
| Leaf -> Leaf
| Node (l, _, _, r) -> join l r
let get_min lt = match lt with
| Leaf -> failwith "empty"
| Node (_, v, _, _) -> v
```
ze strony
``` ocaml
type 'a leftist =
| Leaf
| Node of 'a leftist * 'a * 'a leftist * int
let singleton k = Node (Leaf, k, Leaf, 1)
let rank = function Leaf -> 0 | Node (_,_,_,r) -> r
let rec merge t1 t2 =
match t1,t2 with
| Leaf, t | t, Leaf -> t
| Node (l, k1, r, _), Node (_, k2, _, _) ->
if k1 > k2 then merge t2 t1 (* switch merge if necessary *)
else
let merged = merge r t2 in (* always merge with right *)
let rank_left = rank l and rank_right = rank merged in
if rank_left >= rank_right then Node (l, k1, merged, rank_right+1)
else Node (merged, k1, l, rank_left+1) (* left becomes right due to being shorter *)
let insert x t = merge (singleton x) t
let get_min = function
| Leaf -> failwith "empty"
| Node (_, k, _, _) -> k
let delete_min = function
| Leaf -> failwith "empty"
| Node (l, _, r, _) -> merge l r
```
### z8 :(
### z9
```ocaml=
type 'a clist = { clist : 'z. ('a -> 'z -> 'z) -> 'z -> 'z }
let cnil : = { clist = fun f z -> z}
let ccons a ls = {clist = fun f z -> f a (ls.clist f z)}
let map g ls = {clist = fun f z -> ls.clist (fun a s -> f (g a) s) z}
let append xs ys = {clist = fun f z -> xs.clist f (ys.clist f z)}
let clist_to_list ls = ls.clist List.cons []
let rec clist_of_list xs = match xs with
| [] -> cnil
| x :: xs -> ccons x (clist_of_list xs)
To daje iloczyn kartezjański
let prod ls1 ls2 = ls1.clist (fun a1 z1 -> (ls2.clist (fun a2 z2 -> ccons (a1,a2) z2) z1)) cnil;;
Czy potrafisz zaimplementować funkcję analogiczną do potęgowania? NIE
```
## Lista 3
### z1
#### perm.ml
```ocaml=
module type OrderedType = sig
type t
val compare : t -> t -> int
end
module type S = sig
type key
type t
(** permutacja jako funkcja *)
val apply : t -> key -> key
(** permutacja identycznościowa *)
val id : t
(** permutacja odwrotna *)
val invert : t -> t
(** permutacja która tylko zamienia dwa elementy miejscami *)
val swap : key -> key -> t
(** złożenie permutacji (jako złożenie funkcji) *)
val compose : t -> t -> t
(** porównywanie permutacji *)
val compare : t -> t -> int
end
module Make(Key : OrderedType) = struct
module Ourmap = Map.Make(Key)
type key = Key.t
type t = key Ourmap.t * key Ourmap.t
(** permutacja jako funkcja *)
let apply (perm : t) (value : key) =
if Ourmap.mem value (fst perm)
then Ourmap.find value (fst perm)
else value
(** permutacja identycznościowa *)
let id : t = (Ourmap.empty, Ourmap.empty)
(** permutacja odwrotna *)
let invert (perm : t) =
(snd perm , fst perm)
(** permutacja która tylko zamienia dwa elementy miejscami *)
let swap (e1 : key) (e2 : key) =
let f = (Ourmap.add e1 e2 (Ourmap.add e2 e1 Ourmap.empty))
in (f, f)
(** złożenie permutacji (jako złożenie funkcji) BRZYDKIE *)
(* val compose (perm1 : t) (perm2 : t) =
let map1 = union (fun key v1 v2 -> v2)
(fst perm2)
(Ourmap.filter (fun k v -> Key.compare k v != 0)
(Ourmap.map (apply perm2) (fst perm1)))
in (map1, map2 - odwrotnosc map1)
*)
let compose (perm1 :t) (perm2 : t) =
(Ourmap.merge
(fun (k : key) (v1 : key option) (v2 : key option) ->
match v1,v2 with
| None, None -> None
| _, Some(v) -> let vi = apply perm1 v in
if (Key.compare k vi == 0) then None
else Some(vi)
| Some(v), None -> Some(v)
)
(fst perm1) (fst perm2),
Ourmap.merge
(fun (k : key) (v1 : key option) (v2 : key option) ->
match v1,v2 with
| None, None -> None
| Some(v), _ -> let vi = apply (invert perm2) v in
if (Key.compare k vi == 0) then None
else Some(vi)
| None, Some(v) -> Some(v)
)
(snd perm1) (snd perm2)
)
(** porównywanie permutacji *)
let compare (perm1 : t) (perm2 : t) = Ourmap.compare Key.compare (fst perm1) (fst perm2)
end
```
Testy:
```ocaml=
module PermInt = Perm.Make(Int);;
let lista=[1;2;3;4];;
let perm1=PermInt.id
List.map (PermInt.apply perm1) lista
let perm2=PermInt.swap 2 4
List.map (PermInt.apply perm2) lista
List.map (PermInt.apply (PermInt.invert perm2)) lista
module PermInt = Perm.Make(Int);;
let lista=[1;2;3;4];;
let swap_23 = PermInt.swap 2 3;; (*1 3 2 4*)
let swap_34 = PermInt.swap 3 4;; (*1 2 4 3*)
let swap_24 = PermInt.compose swap_23 swap_34;; (* 1 3 4 2*)
List.map (PermInt.apply swap_24) lista;;
List.map (PermInt.apply (PermInt.invert swap_24)) lista;; (* 1 4 2 3 *)
let swap_32 = PermInt.swap 3 2;;
let my_id = PermInt.compose swap_23 swap_32;;
PermInt.compare my_id PermInt.id;; (* 0 *)
PermInt.compare()
```
- ocamlc -c perm.mli
- ocamlc -c perm.ml
- utop perm.cmo
W utopie :
- open Perm;;
- module PermInt = Perm.Make(Int);;
### z2
#### .mli
``` ocaml
module type OrderedType = sig
type t
val compare : t -> t -> int
end
module type Permutation = sig
type key
type t
(* permutacja jako funkcja *)
val apply : t -> key -> key
(* permutacja identycznosciowa *)
val id : t
(* permutacja odwrotna *)
val invert : t -> t
(* permutacja która zmienia dwa elementy miejscami *)
val swap : key -> key -> t
(* złożenie permutacji (jako złożenie funkcji) *)
val compose : t -> t -> t
(* porównanie permutacji *)
val compare : t -> t -> int
end
module type S = sig
type t
(* czy dany element jest generowany przez zbior *)
val is_generated : t -> t list -> bool
end
module Make(Perm : Permutation) : S with type t = Perm.t
```
#### .ml
```ocaml
module type OrderedType = sig
type t
val compare : t -> t -> int
end
module type Permutation = sig
type key
type t
(* permutacja jako funkcja *)
val apply : t -> key -> key
(* permutacja identycznosciowa *)
val id : t
(* permutacja odwrotna *)
val invert : t -> t
(* permutacja która zmienia dwa elementy miejscami *)
val swap : key -> key -> t
(* złożenie permutacji (jako złożenie funkcji) *)
val compose : t -> t -> t
(* porównanie permutacji *)
val compare : t -> t -> int
end
module type S = sig
type t
(* czy dany element jest generowany przez zbior *)
val is_generated : t -> t list -> bool
end
module Make(Perm : Permutation) = struct
type t = Perm.t
module PermSet = Set.Make(Perm)
let is_generated (perm : t) (perm_lst : t list) =
let s = PermSet.add Perm.id (PermSet.of_list perm_lst) in
let rec inner (perm : t) (perm_set : PermSet.t) =
if PermSet.mem perm perm_set then true
else let next_set =
PermSet.fold (fun el acc ->
PermSet.union acc
(PermSet.add (Perm.invert el)
(PermSet.fold (fun ell acc->
PermSet.add (Perm.compose el ell) acc )
perm_set PermSet.empty)))
perm_set
perm_set
in if compare next_set perm_set == 0 then false
else inner perm next_set
in inner perm s
end
```
ocamlc -c gen_perm.ml
utop perm.cmo gen_perm.cmo
Testy
```ocaml=
open Perm;;
open Genperm;;
module PermInt = Perm.Make(Int);;
module GenpermInt = Genperm.Make(PermInt);;
GenpermInt.is_generated (PermInt.swap 2 3) [PermInt.swap 2 3];;
let swap_23 = PermInt.swap 2 3;;
let swap_34=PermInt.swap 3 4;;
let swap_24 = PermInt.compose swap_34 swap_23;;
GenpermInt.is_generated swap_24 [swap_23;swap_34];;
GenpermInt.is_generated swap_24 [PermInt.swap 2 5 ;swap_34];;
```
### z3, z4, z5, z6 :-0
Logic.ml
``` ocaml
type formula =
| My_False
| Variable of string
| Implication of formula * formula
let rec string_of_formula f = match f with
| My_False -> "⊥"
| Variable c -> c
| Implication(My_False, r) -> "⊥ -> " ^ string_of_formula r
| Implication(Variable c, r) -> c ^ " -> " ^ string_of_formula r
| Implication(l, r) -> "(" ^ string_of_formula l ^ ")" ^ " -> " ^ string_of_formula r
let pp_print_formula fmtr f =
Format.pp_print_string fmtr (string_of_formula f)
type theorem = | Theorem of formula list * formula
let assumptions thm = match thm with
| Theorem(a, c) -> a
let consequence thm = match thm with
| Theorem(a, c) -> c
let pp_print_theorem fmtr thm =
let open Format in
pp_open_hvbox fmtr 2;
begin match assumptions thm with
| [] -> ()
| f :: fs ->
pp_print_formula fmtr f;
fs |> List.iter (fun f ->
pp_print_string fmtr ",";
pp_print_space fmtr ();
pp_print_formula fmtr f);
pp_print_space fmtr ()
end;
pp_open_hbox fmtr ();
pp_print_string fmtr "⊢";
pp_print_space fmtr ();
pp_print_formula fmtr (consequence thm);
pp_close_box fmtr ();
pp_close_box fmtr ()
let by_assumption f = Theorem([f], f)
let imp_i f thm = Theorem(List.filter (fun x -> not(x = f)) (assumptions thm),
Implication(f, consequence thm))
let difference_of_lists xs ys =
List.filter (fun x -> not (List.mem x ys)) xs
let imp_e th1 th2 = match consequence th1 with
| Implication(fi, f) -> if (fi = consequence th2)
then Theorem(difference_of_lists (assumptions th1) (assumptions th2) @ assumptions th2, f)
else failwith "not equal"
| _ -> failwith "incorrect th1"
let bot_e f thm = match consequence thm with
| My_False -> Theorem(assumptions thm, f)
| _ -> failwith "incorrect theorem"
(* ⊢ p → p*)
(*⊢ p → q → p*)
(*⊢ (p → q → r) → (p → q) → p → r*)
(*⊢ ⊥ → p*)
(*
open Logic;;
#install_printer pp_print_formula ;;
#install_printer pp_print_theorem ;;
*)
```
W Logic.mli
```ocaml=
type formula =
| Implication of formula * formula
| Variable of string
| MyFalse
```
### z7 :-|
```ocaml=
(* ⊢ p → p*)
imp_i (Variable "p") (by_assumption (Variable "p"));;
(*⊢ p → q → p*)
imp_i (Variable "p") (imp_i (Variable "q") (by_assumption (Variable "p")));;
(*⊢ (p → q → r) → (p → q) → p → r*)
let pqrL = (Implication (Variable "p", Implication (Variable "q", Variable "r")))
let pqL = Implication (Variable "p", Variable "q")
let pqrT = by_assumption pqrL
let pT = by_assumption (Variable "p")
let qrT = imp_e pqrT pT
let pqT = by_assumption pqL
let qT = imp_e pqT pT
let rT = imp_e qrT qT
let prT = imp_i (Variable "p") rT
let pqprT = imp_i pqL prT
pqrpqprT = imp_i pqrL pqprT;;
(*⊢ ⊥ → p*)
imp_i My_False (bot_e (Variable "p") (by_assumption My_False));;
(imp_i (Variable "q") (by_assumption (Variable "p")))
```
## Lista 4
### zadanie 1
### zadanie 2
### zadanie 3-6
proof.ml
```ocaml
open Logic
type lbl_assump = (string * Logic.formula)
type incomplete_proof =
| Goal of lbl_assump list * Logic.formula
| IBot_e of lbl_assump list * Logic.formula * incomplete_proof
| IImp_e of lbl_assump list * Logic.formula * incomplete_proof * incomplete_proof
| IImp_i of lbl_assump list * Logic.formula * incomplete_proof
| IComplete of Logic.theorem
type context =
| CEmpty
| CGoal of lbl_assump list * Logic.formula
| CBot_e of context * lbl_assump list * Logic.formula
| CImp_e of context * lbl_assump list * Logic.formula * incomplete_proof
| CImp_i of context * lbl_assump list * Logic.formula
| CComplete of Logic.theorem
type proof =
| Complete of Logic.theorem
| Incomplete of incomplete_proof * context
let proof g f =
Incomplete (Goal(g, f), CEmpty)
let qed pf =
match pf with
| Complete(t) -> t
| _ -> failwith "incompleted proof"
let goal pf =
match pf with
| Complete(t) -> None
| Incomplete(ip, _) ->
match ip with
| Goal (g, f) -> Some (g, f)
| _ -> failwith "not a goal"
let rec goal_down incomplete_proof ctx =
match incomplete_proof with
| Goal (g, f) -> Some(Incomplete(incomplete_proof, ctx))
| IBot_e (g, f, i) -> goal_down i (CBot_e(ctx, g, f))
| IImp_e (g, f, i1, i2) ->
begin
match i1 with
| IComplete _ -> goal_down i2 (CImp_e(ctx, g, f, i1))
| _ -> goal_down i1 (CImp_e(ctx, g, f, i2))
end
| IImp_i (g, f, i) -> goal_down i (CImp_i(ctx, g, f))
| IComplete (_) -> None
let rec goal_up incomplete_proof ctx =
match ctx with
| CEmpty -> None
| CGoal (g, f) -> failwith "surely won't happen"
| CBot_e (ctx, g, f) -> goal_up (IBot_e(g, f, incomplete_proof)) ctx
| CImp_e (ctx, g, f, i2) ->
begin
match i2 with
| IComplete (_) -> goal_up (IImp_e(g, f, incomplete_proof, i2)) ctx
| _ -> goal_down i2 (CImp_e(ctx, g, f, incomplete_proof))
end
| CImp_i (ctx, g, f) -> goal_up (IImp_i(g, f, incomplete_proof)) ctx
| CComplete (_)-> None
let next pf =
match pf with
| Complete _ -> pf
| Incomplete (ipf, ctx) ->
match goal_down ipf ctx with
| None ->
begin
match goal_up ipf ctx with
| None -> failwith "You shouldn't be here"
| Some pf -> pf
end
| Some pf -> pf
let intro name pf =
match pf with
| Complete _ -> failwith "ups"
| Incomplete (ipf,ctx) ->
match ipf with
| Goal (assm, Logic.Implication(f1, f2)) ->
Incomplete (IImp_i (assm, Logic.Implication(f1, f2), Goal((name, f1)::assm, f2)), ctx)
| _ -> failwith "ups v2"
let apply f pf =
let apply_thm thm pf =
(* TODO: zaimplementuj *)
failwith "not implemented"
let apply_assm name pf =
(* TODO: zaimplementuj *)
failwith "not implemented"
let pp_print_proof fmtr pf =
match goal pf with
| None -> Format.pp_print_string fmtr "No more subgoals"
| Some(g, f) ->
Format.pp_open_vbox fmtr (-100);
g |> List.iter (fun (name, f) ->
Format.pp_print_cut fmtr ();
Format.pp_open_hbox fmtr ();
Format.pp_print_string fmtr name;
Format.pp_print_string fmtr ":";
Format.pp_print_space fmtr ();
Logic.pp_print_formula fmtr f;
Format.pp_close_box fmtr ());
Format.pp_print_cut fmtr ();
Format.pp_print_string fmtr (String.make 40 '=');
Format.pp_print_cut fmtr ();
Logic.pp_print_formula fmtr f;
Format.pp_close_box fmtr ()
```
v2 (tylko zmienione funkcje)
```ocaml=
type goal = lbl_assump list * Logic.formula
type proof =
| Complete of Logic.theorem
| Incomplete of goal * context
let proof g f =
Incomplete ((g, f), CEmpty)
let rec goal pf =
match pf with
| Complete(t) -> None
| Incomplete(ip, _) -> Some(ip)
```
## Lista 5
### zadanie 1
``` ocaml
let fib_f fib n =
if n <= 1 then n
else fib (n-1) + fib (n-2)
let rec fix f x = f (fix f) x
let fib = fix fib_f
let rec fix_with_limit n f x =
if (n != 0)
then f (fix_with_limit (n - 1) f) x
else failwith "Limit exceeded";;
let memo = Hashtbl.create 1000;;
let rec fix_memo f x =
match Hashtbl.find_opt memo (Hashtbl.hash x) with
| Some c -> c
| None -> let a = f (fix_memo f) x in
begin
Hashtbl.add memo (Hashtbl.hash x) a;
a
end
```
### zadanie 3
``` ocaml
type 'a lazy_tree =
| LazyNode of (unit -> 'a lazy_tree) * 'a * (unit -> 'a lazy_tree)
let rec lazy_fraction_tree a b c d =
LazyNode (
(fun () ->
lazy_fraction_tree a b (a + c) (b + d)),
(a + c, b + d),
(fun () ->
lazy_fraction_tree (a + c) (b + d) c d)
)
```
### zadanie 4 rozwarstwia sie :(
``` ocaml
type 'a dllist = 'a dllist_data lazy_t
and 'a dllist_data =
{ prev : 'a dllist;
elem : 'a;
next : 'a dllist
}
let prev : 'a dllist -> 'a dllist =
function xs -> (Lazy.force xs).prev
let elem : 'a dllist -> 'a =
function xs -> (Lazy.force xs).elem
let next : 'a dllist -> 'a dllist =
function xs -> (Lazy.force xs).next
let rec of_list (xs : 'a list) : 'a dllist =
match xs with
| [] -> failwith "empty list"
| x :: [] -> let rec dd = lazy {prev = dd; elem = x; next = dd} in dd
| x :: y :: [] ->
let rec ds = lazy {prev = dd; elem = x; next = dd}
and
dd = lazy {prev = ds; elem = y; next = ds} in ds
| x :: xs ->
lazy {prev = of_list (begin match List.rev (x::xs) with
| y :: ys -> y :: List.rev ys
|_ -> failwith "err" end);
elem = x;
next = of_list (xs @ x :: [])}
let xs = of_list [8;9;10]
let () = assert (elem xs = 8)
let () = assert (elem (prev (next xs)) = elem xs)
(*
let () = assert (prev (next xs) == xs) (* :( *)
*)
```
### zadanie 6
``` ocaml
type 'a to_lazy =
| Lazy of (unit -> 'a)
| Value of 'a
| Evaluating
type 'a my_lazy = 'a to_lazy ref
let force : 'a my_lazy -> 'a =
fun ml ->
match !ml with
| Lazy f ->
ml := Evaluating;
let v = f () in
ml := Value(v);
v
| Value v -> v
| Evaluating -> failwith "Evaluating"
let fix (f : 'a my_lazy -> 'a) : 'a my_lazy =
let rec lazy_value = ref (Lazy (fun () -> f lazy_value)) in
lazy_value
type 'a lazy_list =
| Nil
| Cons of 'a * 'a lazy_list my_lazy
let hd : 'a lazy_list -> 'a =
function
| Nil -> failwith "Empty list"
| Cons(x, _) -> x
let tl : 'a lazy_list -> 'a lazy_list =
function
| Nil -> failwith "Empty list"
| Cons(_, xs) -> force xs
let rec nth : 'a lazy_list -> int -> 'a =
fun ll n ->
if n < 0 then failwith "Index out of bounds"
else
if n == 0 then hd ll
else nth (tl ll) (n - 1)
let stream_of_ones : int lazy_list my_lazy =
fix (fun stream_of_ones -> Cons (1, stream_of_ones))
(*
nth (force stream_of_ones) 5
*)
```
### zadanie 7
``` ocaml
type 'a to_lazy =
| Lazy of (unit -> 'a)
| Value of 'a
| Evaluating
type 'a my_lazy = 'a to_lazy ref
let force : 'a my_lazy -> 'a =
fun ml ->
match !ml with
| Lazy f ->
ml := Evaluating;
let v = f () in
ml := Value(v);
v
| Value v -> v
| Evaluating -> failwith "Evaluating"
let fix (f : 'a my_lazy -> 'a) : 'a my_lazy =
let rec lazy_value = ref (Lazy (fun () -> f lazy_value)) in
lazy_value
(* z7 ---------------------------------------------------- *)
type 'a lazy_list =
| Nil
| Cons of 'a * 'a lazy_list my_lazy
let rec nth xs n =
match xs with
| Nil -> raise Not_found
| Cons(x, xs) ->
if n = 0 then x
else nth (force xs) (n-1)
let rec filter (p : 'a -> bool) (xs : 'a lazy_list) : ('a lazy_list) =
match xs with
| Nil -> Nil
| Cons(x, xs) when p x -> Cons(x, ref (Lazy (fun () -> (filter p (force xs)))))
| Cons(_, xs) -> filter p (force xs)
let rec take_while p xs =
match xs with
| Cons(x, xs) when p x -> Cons(x, ref (Lazy (fun () -> (take_while p (force xs)))))
| _ -> Nil
let rec for_all p xs =
match xs with
| Nil -> true
| Cons(x, xs) -> p x && for_all p (force xs)
let rec nats_from n =
Cons(n, ref (Lazy (fun () -> (nats_from (n+1)))))
let nats = nats_from 0
let rec primes =
Cons(2, ref (Lazy (fun () -> (filter is_prime (nats_from 3)))))
and is_prime n =
primes
|> take_while (fun p -> p * p <= n)
|> for_all (fun p -> n mod p <> 0)
```
### zadanie 8
``` ocaml
open Seq
type _ fin_type =
| Unit : unit fin_type
| Bool : bool fin_type
| Pair : 'a fin_type * 'b fin_type -> ('a * 'b) fin_type
let rec all_values : type a. a fin_type -> a Seq.t =
fun ftype -> match ftype with
| Unit -> List.to_seq [()]
| Bool -> List.to_seq [true; false]
| Pair (fst_type, snd_type) ->
flat_map
(fun fst_val ->
map (fun snd_val -> (fst_val, snd_val))
(all_values snd_type))
(all_values fst_type)
```
### zadanie 9
``` ocaml
type _ fin_type =
| Unit : unit fin_type
| Bool : bool fin_type
| Pair : 'a fin_type * 'b fin_type -> ('a * 'b) fin_type
| Empty : empty fin_type
| Either : 'a fin_type * 'b fin_type -> ('a, 'b) Either.t fin_type
and empty = |
let rec all_values : type a. a fin_type -> a Seq.t =
function
| Unit -> List.to_seq [()]
| Bool -> List.to_seq [true; false]
| Pair (a, b) ->
Seq.flat_map
(fun x ->
Seq.map
(fun y -> (x, y))
(all_values b))
(all_values a)
| Empty -> Seq.empty
| Either (a, b) ->
let av = all_values a and bv = all_values b in
Seq.append
(Seq.map (fun x -> Either.left x) av)
(Seq.map (fun y -> Either.right y) bv)
```
### zadanie 10
```ocaml
module Seq = struct
include Seq
let rec for_all : ('a -> bool) -> 'a Seq.t -> bool =
fun pred seq ->
match seq () with
| Seq.Nil -> true
| Seq.Cons (x, xs) -> pred x && for_all pred xs
let is_empty seq =
match seq () with
| Seq.Nil -> true
| _ -> false
end
type _ fin_type =
| Unit : unit fin_type
| Bool : bool fin_type
| Pair : 'a fin_type * 'b fin_type -> ('a * 'b) fin_type
| Empty : empty fin_type
| Either : 'a fin_type * 'b fin_type -> ('a, 'b) Either.t fin_type
| Function : 'a fin_type * 'b fin_type -> ('a -> 'b) fin_type
and empty = |
let rec all_values : type a. a fin_type -> a Seq.t =
function
| Unit -> List.to_seq [()]
| Bool -> List.to_seq [true; false]
| Pair (a, b) ->
Seq.flat_map
(fun x ->
Seq.map
(fun y -> (x, y))
(all_values b))
(all_values a)
| Empty -> Seq.empty
| Either (a, b) ->
let av = all_values a and bv = all_values b in
Seq.append
(Seq.map (fun x -> Either.Left x) av)
(Seq.map (fun y -> Either.Right y) bv)
| Function (a, b) ->
all_functions a Seq.empty (all_values a) (all_values b)
and equal_at : type a. a fin_type -> a -> a -> bool =
fun ty x y ->
match ty with
| Unit -> x = y
| Bool -> x = y
| Pair (a, b) ->
equal_at a (fst x) (fst y) &&
equal_at b (snd x) (snd y)
| Empty -> true
| Either (a, b) ->
(match (x, y) with
| (Left x, Left y) -> equal_at a x y
| (Right x, Right y) -> equal_at b x y
| _ -> false)
| Function (a, b) ->
let all_inputs = all_values a in
Seq.for_all (fun input -> equal_at b (x input) (y input)) all_inputs
and all_functions : type a b. a fin_type -> (a -> b) Seq.t -> a Seq.t -> b Seq.t -> (a -> b) Seq.t =
fun t seq a b ->
match a () with
| Seq.Nil -> seq
| Seq.Cons (a, xs) ->
let seq =
if Seq.is_empty seq then
Seq.map (fun b -> fun _ -> b) b
else
Seq.flat_map
(fun f ->
Seq.map (fun b ->
fun x -> if (equal_at t x a) then b
else f x) b)
seq
in all_functions t seq xs b
(* test *)
let xs = all_values (Function(Bool, Bool))
let ys = Seq.map (fun x -> List.map (fun y -> x y) (List.of_seq (all_values Bool))) xs
let ls = List.of_seq ys
```
## Lista 6
### zadanie 1
``` ocaml
type ('a, 'b) format = (string -> 'b) -> string -> 'a
let int (k : string -> 'a) =
fun (s : string) (i : int) -> k (s ^ (string_of_int i))
let str (k : string -> 'a) =
fun (s1 : string) (s2 : string) -> k (s1 ^ s2)
let lit (sn : string) (k : string -> 'a) =
fun (s : string) -> k(s ^ sn)
let (^^) (f1 : ('a, 'b) format) (f2 : ('b, 'c) format) (k : string -> 'c) =
f1(f2 k)
let ksprintf (f : ('a, 'b) format) (k : string -> 'b) =
f k ""
let sprintf (f : ('a, string) format) =
ksprintf f (fun x -> x);;
sprintf (lit "Ala ma " ^^ _int ^^ lit " kot" ^^ _str ^^ lit ".") 5 "ów"
```
### zadanie 2
``` ocaml
```
### zadanie 3
``` ocaml
exception Error of string
let for_all pred ls =
try List.fold_left (fun acc a -> if not (pred a) then raise (Error "oops") else acc) true ls with Error _ -> false
let mult_list ls =
try List.fold_left (fun acc a -> if a==0 then raise (Error "mult") else acc*a) 1 ls with Error _ ->0
let sorted ls=
try fst(List.fold_left (fun acc a ->
if a < snd(acc)
then raise (Error "unsort")
else (true, a))
(true, (List.hd ls))
(List.tl ls))
with Error _ -> false
```
### zadanie 4
``` ocaml
let rec fold_left_cps f acc xs=
match xs with
| [] -> acc
| x::xs -> f acc x (fun lacc -> fold_left_cps f lacc xs)
let fold_left f acc xs=
fold_left_cps (fun acc x k -> k (f acc x)) acc
```
### zadanie 5
``` ocaml
let for_all pred xs =
fold_left_cps (fun acc x k ->
if pred x
then k acc
else false
) true xs
let mult_list xs =
fold_left_cps (fun acc x k ->
if x==0
then 0
else k (acc * x)
) 1 xs
let sorted xs =
fold_left_cps (fun acc x k ->
if x>snd(acc)
then k (true,x)
else (false,x)
) (true,(List.hd xs)) (List.tl xs)
|> fst
```
## Lista 7
### zadanie 1, 2
```ocaml
module type RandomMonad = sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
val random : int t
end
module RS : sig
include RandomMonad
val run : int -> 'a t -> 'a
end = struct
type 'a t = int -> 'a * int
let return x seed = (x, seed)
let run seed f = fst (f seed)
let random a =
let b = 16807 * (a mod 127773) - 2836 * (a / 127773) in
if b > 0 then (b, b) else (b + 2147483647, b + 2147483647)
(* (x : int -> 'a * int) (f : 'a -> int -> 'b * int) -> (int -> 'b * int) *)
let bind x f =
fun s1 -> let (v, s2) = x s1 in
f v s2
end
module Shuffle(R : RandomMonad) : sig
val shuffle : 'a list -> 'a list R.t
end = struct
let rec chosen_rest idx xs =
match xs with
| [] -> failwith "empty list"
| x :: xs ->
if idx = 0 then (x, xs)
else let (v, xs) = chosen_rest (idx - 1) xs in
(v, x :: xs)
let rec shuffle xs =
match xs with
| [] -> R.return []
| _ ->
R.bind
R.random
(fun r -> let idx = r mod List.length xs in
let (hd, tl) = chosen_rest idx xs in
R.bind (shuffle tl) (fun shuffled_tl -> R.return (hd :: shuffled_tl)))
end
(*
module SH = Shuffle(RS);;
RS.run 0 (SH.shuffle [1;2;3;4;5;6;7;8]);;
RS.run 23 (SH.shuffle [1;2;3;4;5;6;7;8]);;
RS.run 1 (RS.bind RS.random (fun x -> RS.return (RS.run x RS.random)));;
*)
```
### zadanie 3
```ocaml
module IdMonad : sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
end = struct
type 'a t = 'a
let return x = x
let bind x f = f x
end
module DeferredMonad : sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
end = struct
type 'a t = unit -> 'a
let return x = fun () -> x
let bind x f = f (x ())
end
```
### zadanie 4
#### er
``` ocaml
module type Monad = sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
end
module Err : sig
include Monad
val fail : 'a t
val catch : 'a t -> (unit -> 'a t) -> 'a t
val run : 'a t -> 'a option
end = struct
type 'r ans = 'r option
type 'a t = { run : ('a -> 'a ans) -> 'a ans }
let run m = m.run (fun a -> Some a)
let return x = {run = fun cont -> cont x}
let fail = {run = fun _ -> None}
let bind m f =
{ run = fun cont ->
match run m with
| None -> None
| Some x -> (f x).run cont }
let catch m f =
{ run = fun cont ->
match run m with
| Some x -> Some x
| None -> (f ()).run cont }
end
Err.run (Err.bind (Err.return 1) (fun x -> Err.return (x+1)));;
```
#### bt
``` ocaml
module type Monad = sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
end
module BT : sig
include Monad
val fail : 'a t
val flip : bool t
val run : 'a t -> 'a Seq.t
end = struct
type 'r ans = 'r Seq.t
type 'a t = { run : ('a -> 'a ans) -> 'a ans }
let run m = m.run (fun a -> List.to_seq [a])
let return x = {run = fun cont -> cont x}
let fail = {run = fun _ -> Seq.empty}
let flip =
{ run = fun cont ->
Seq.flat_map cont (List.to_seq [true; false]) }
let bind m f =
{ run = fun cont ->
Seq.flat_map (fun a -> (f a).run cont) (run m) }
end
let (let* ) = BT.bind
let rec select a b =
if a >= b then BT.fail
else
let* c = BT.flip in
if c then BT.return a
else select (a+1) b
let triples n =
let* a = select 1 n in
let* b = select a n in
let* c = select b n in
if a*a + b*b = c*c then BT.return (a, b, c)
else BT.fail
```
``` ocaml
module type Monad = sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
end
module St(State : sig type t end) : sig
include Monad
val get : State.t t
val set : State.t -> unit t
val run : State.t -> 'a t -> 'a
end = struct
type 'a ans = State.t -> 'a * State.t
type 'a t = { run : 'r. ('a -> 'r ans) -> 'r ans }
let return x = {run = fun cont -> cont x}
let run s m = fst (m.run (fun a s2 -> (a, s2)) s)
let set s = {
run = fun cont _ -> cont () s
}
let get = {
run = fun cont s -> cont s s
}
let bind m f ={
run = fun cont ->
m.run (fun a -> (f a).run cont)
}
end
module CounterState = struct
type t = int
end
module CounterMonad = St(CounterState)
open CounterMonad
let increment_and_get : int t =
bind get (fun current_count ->
bind (set (current_count + 1)) (fun () ->
return current_count
)
)
let example () =
let initial_state = 0 in
let result = run initial_state increment_and_get in
Printf.printf "Final Counter Value: %d\n" result
(* Run the example *)
let () = example ()
```
### Zadanie 5
```ocaml!
type 'a regexp =
| Eps
| Lit of ('a -> bool)
| Or of 'a regexp * 'a regexp
| Cat of 'a regexp * 'a regexp
| Star of 'a regexp
let ( +% ) r1 r2 = Or(r1, r2)
let ( *% ) r1 r2 = Cat(r1, r2)
(** Obliczenia z nawrotami *)
module BT : sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
(** Brak wyniku *)
val fail : 'a t
(** Niedeterministyczny wybór -- zwraca true, a potem false *)
val flip : bool t
val run : 'a t -> 'a Seq.t
end = struct
(* Obliczenie typu 'a to leniwa lista wszystkich możliwych wyników *)
type 'a t = 'a Seq.t
let return x = List.to_seq [ x ]
let rec bind m f = Seq.flat_map f m
let fail = Seq.empty
let flip = List.to_seq [ true; false ]
let run m = m
end
let rec match_regexp (regex : 'a regexp) (xs : 'a list) : 'a list option BT.t =
match regex, xs with
| Eps, [] -> BT.return None
| Eps, xs -> BT.return (Some xs)
| Lit _, [] -> BT.fail
| Lit p, x :: xs ->
if p x then BT.return (Some xs)
else BT.fail
| Or (r1, r2), _ ->
BT.bind BT.flip (fun flip_opt ->
if flip_opt then match_regexp r1 xs else match_regexp r2 xs)
| Cat (r1, r2), _ ->
BT.bind (match_regexp r1 xs) (fun result ->
match result with
| Some x -> match_regexp r2 x
| None -> match_regexp r2 xs)
| Star r, _ -> BT.bind (match_regexp r xs) (fun res ->
match res with
| Some ys -> BT.bind BT.flip (fun flip_opt ->
if flip_opt then BT.return (Some ys)
else match_regexp (Star r) ys)
| None -> BT.fail)
(* | Star r, _ ->
BT.bind BT.flip (fun flip_opt ->
if flip_opt then
BT.return None
else
match_regexp (Cat (r, Star r)) xs) *)
(*
List.of_seq
(BT.run
(match_regexp
(Lit ((<>) 'a'))
['b';'c']));;
List.of_seq
(BT.run
(match_regexp
(Star (Lit ((<>) 'o')))
['s';'a';'k';'o';'p']));;
List.of_seq
(BT.run
(match_regexp
(Star (Star (Lit ((<>) 'k'))))
['x';'a';'k']));;
List.of_seq
(BT.run
(match_regexp
(Star (Star (Lit ((<>) 'b')) +% (Lit ((=) 'b') *% Lit ((=) 'a'))))
['s';'a';'k';'o';'p']));;
Or działa z potencjalnymi duplikatami, stary też ale bez None
*)
```
### Zadanie 6
```ocaml!
module SBT(State : sig type t end) : sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
val fail : 'a t
val flip : bool t
val get : State.t t
val put : State.t -> unit t
val run : State.t -> 'a t -> 'a Seq.t
end = struct
type 'a t = State.t -> ('a * State.t) Seq.t
let return x s = List.to_seq [(x, s)]
let flip s = List.to_seq [(true, s); (false, s)]
let get s = List.to_seq [(s, s)]
let put s1 _ = List.to_seq [((), s1)]
let fail _ = Seq.empty
let run s m = Seq.map (fun x -> fst x) (m s)
let bind m f s =
Seq.flat_map (fun x -> f (fst x) (snd x)) (m s)
end
```
### zadanie 8
```
type symbol = string
type 'v term =
| Var of 'v
| Sym of symbol * 'v term list
let return (a: 'v): 'v term =
Var(a)
let rec bind (a: 'v term) (f: 'v -> 'v term): 'v term =
match a with
| Var v -> f v
| Sym (sym, terms) -> Sym(sym, List.map (fun t -> bind t f) terms)
```
## Lista 8
### zadania ?-?, trochę działa
```haskell=
{-# LANGUAGE LambdaCase #-}
import Data.Char (toLower)
import System.IO (isEOF)
main :: IO ()
main = putStrLn ":)"
-- z1
echoLower :: IO ()
echoLower = do
input <- getLine
if not (null input)
then do
putStrLn $ map Data.Char.toLower input
echoLower
else
return ()
-- z2
data StreamTrans i o a
= Return a
| ReadS (Maybe i -> StreamTrans i o a)
| WriteS o (StreamTrans i o a)
toLower :: StreamTrans Char Char ()
toLower =
ReadS $ \case
Just c -> WriteS (Data.Char.toLower c) Main.toLower
Nothing -> Return ()
runIOStreamTrans :: StreamTrans Char Char a -> IO a
runIOStreamTrans (Return a) = return a
runIOStreamTrans (ReadS f) = do
input <- getChar
if input == '\n'
then runIOStreamTrans (f Nothing)
else do
runIOStreamTrans (f (Just input))
runIOStreamTrans (WriteS o st) = do
putChar '\n'
putChar o
putChar '\n'
runIOStreamTrans st
-- z3
listTrans :: StreamTrans i o a -> [i] -> ([o], a)
listTrans (Return a) xs = ([], a)
listTrans (ReadS f) [] = listTrans (f Nothing) []
listTrans (ReadS f) (x:xs) = listTrans (f (Just x)) xs
listTrans (WriteS o cont) xs =
let (output, result) = listTrans cont xs
in (o : output, result)
-- z6
catchOutput :: StreamTrans i o a -> StreamTrans i b (a, [o])
catchOutput (Return a) = return (a, [])
catchOutput (ReadS f) = do
input <- getChar
if input == '\n'
then catchOutput (f Nothing)
else do
catchOutput (f (Just input))
catchOutput (WriteS o st) =
catchOutput ( ReadS $ \case
Just c -> WriteS (o : c : []) st
Nothing -> Return ())
-- z7
data BF
= MoveR -- >
| MoveL -- <
| Inc -- +
| Dec -- -
| Output -- .
| Input -- ,
| While [BF]-- [ ]
brainfuckParser :: StreamTrans Char BF ()
brainfuckParser =
ReadS $ \case
Just c -> WriteS (parse c) brainfuckParser
Nothing -> Return ()
parse :: Char -> BF
parse '>' = MoveR
parse '<' = MoveL
parse '+' = Inc
parse '-' = Dec
parse ',' = Input
parse '.' = Output
```