import Lectures.LoVe.LoVelib
/-!
Exercícios da Aula 6: Programação Funcional.
Cada tipo é dado. Defina as funções e prove as leis,
substituindo `sorry`. Toda lei aqui vale por `rfl` ou `decide`.
Os exercícios 9 e 10 são opcionais.
-/
namespace FuncEx

inductive Direction where
  | north | east | south | west
  deriving DecidableEq

def turnRight : Direction → Direction :=
  sorry

theorem turn_four :
    turnRight (turnRight (turnRight
      (turnRight Direction.north))) = Direction.north :=
  sorry

end FuncEx

namespace FuncEx

def lastOpt {α : Type} : List α → Option α :=
  sorry

theorem last_opt_nil {α : Type} :
    lastOpt ([] : List α) = none :=
  sorry

theorem last_opt_example :
    lastOpt [3, 1, 4] = some 4 :=
  sorry

end FuncEx

namespace FuncEx

structure Rectangle where
  width : ℕ
  height : ℕ

def area (r : Rectangle) : ℕ :=
  sorry

theorem area_example :
    area { width := 3, height := 4 } = 12 :=
  sorry

end FuncEx

namespace FuncExBox

structure Rectangle where
  width : ℕ
  height : ℕ

structure Box extends Rectangle where
  depth : ℕ

def volume (b : Box) : ℕ :=
  sorry

theorem volume_example :
    volume { width := 2, height := 3, depth := 4 } = 24 :=
  sorry

end FuncExBox

namespace FuncEx

class Doubler (α : Type) where
  dup : α → α

instance : Doubler ℕ :=
  sorry

instance {α : Type} : Doubler (List α) :=
  sorry

def applyDup {α : Type} [Doubler α] (a : α) : α :=
  sorry

theorem dup_nat : applyDup (3 : ℕ) = 6 :=
  sorry

end FuncEx

namespace FuncEx

inductive Tree (α : Type) where
  | leaf
  | branch (l : Tree α) (x : α) (r : Tree α)

def leaves {α : Type} : Tree α → ℕ :=
  sorry

def nodes {α : Type} : Tree α → ℕ :=
  sorry

def tx : Tree ℕ :=
  .branch (.branch .leaf 1 .leaf) 2 .leaf

theorem leaves_nodes : leaves tx = nodes tx + 1 :=
  sorry

end FuncEx

namespace FuncEx

def replicate {α : Type} : ℕ → α → List α :=
  sorry

theorem replicate_zero {α : Type} (x : α) :
    replicate 0 x = [] :=
  sorry

end FuncEx

namespace FuncEx

def isEmpty {α : Type} : List α → Bool :=
  sorry

theorem is_empty_nil {α : Type} :
    isEmpty ([] : List α) = true :=
  sorry

theorem is_empty_cons {α : Type} (x : α)
    (xs : List α) : isEmpty (x :: xs) = false :=
  sorry

end FuncEx

namespace FuncEx

inductive Rose (α : Type) where
  | node (x : α) (children : List (Rose α))

def rsize {α : Type} : Rose α → ℕ :=
  sorry

end FuncEx

namespace FuncEx

inductive Vec (α : Type) : ℕ → Type where
  | nil : Vec α 0
  | cons {n : ℕ} : α → Vec α n → Vec α (n + 1)

def vhead {α : Type} {n : ℕ} : Vec α (n + 1) → α :=
  sorry

def vx : Vec ℕ 2 := .cons 3 (.cons 4 .nil)

end FuncEx

