Contato: | thanos@imd.ufrn.br |
Playlist: | IRI |
Monitoria/TA: | fmc.imd.ufrn.br |
Turmas self: | ../ |
Turmas FMC1: | /teaching/fmc1 |
Info
Pré-requisitos
O IntroProof.
Além disso, é necessário que tu tens tempo e vontade para estudar, fazer os trabalhos atribuídos, etc.
(Obs.: estudar ≠ ler.)
Conteúdo
(Baseado no módulo correspondentes desta proposta.)
Os naturais e o tipo Nat
; seus construtores (zero, sucessor) e sua teoria: implementação recursiva das suas principais operações, e verificação indutiva das suas principais propriedades. O tipo dos booleanos, Bool
. Ordens sobre os naturais: especificação e verificação de suas propriedades. Outras funções e relações, e suas propriedades. Indução como princípio e técnica de demonstração em matemática. A unicidade dos naturais (a menos de isomorfismo). List Nat
e List α
: tipos de dados de listas: implementação recursiva e verificação indutiva de suas principais propriedades. Outros tipos de dados recursivos: tipos de árvores; tipos de expressões aritméticas; tipos de fórmulas; termos de cálculo-λ. Numerais binários, definição de semântica e seu uso para verificação de corretude.
Objetivos de aprendizagem
Neste módulo estudamos como definir tipos de dados, funções, e relações recursivamente, e como demonstrar propriedades sobre tais coleções de dados por indução.
Prática com o uso da linguagem matemática e das principais técnicas de demonstração e refutação. Prática com a escrita de definições por recursão e demonstrações por indução. Recursão e indução estrutural sobre tipos de dados recursivos. Apreciação de coleções potencialmente infinitas do ponto de vista implementacional, recursivo, e verificação matemática de suas propriedades de interesse. Casamento de padrões e seu uso em definições, demonstrações, e cálculos. Recursão mútua, indução aninhada. Ganhar familiaridade com inferência de tipos e evitar erros de tipagem. Notação e nomenclatura matemática e computacional. Apreciar a diferença e a conexão entre sintaxe e semântica.
Bibliografia e referências
Conhece o libgen?
Principal
- Eu: Matemática fundacional para computação [fmcbook] (Capítulo 4)
Auxiliar
- Bird & Wadler (1986): Introduction to Functional Programming (Cap. 1,2,3,5,9)
- Mendelson (1973): Number Systems and the Foundations of Analysis (Cap. 2)
- Avigad, Lewis, van Doorn (2017): Logic and Proof (Cap. 17)
- Avigad, de Moura, and Soonho Kong (2017): Theorem proving in Lean (Cap: 7,8)
- Steffen, Rüthing, Huth (2018): Mathematical Foundations of Advanced Informatics, vol 1 (Cap: 4, 5)
- Hutton (2016): Programming in Haskell, 2nd ed.
- Pierce et al.: Software Foundations, Vol 1 (Cap: Basics, Induction, Lists)
- Fejer, Simovici (1991): Mathematical Foundations of Computer Science, Vol 1 (Cap. 4)
Para cada um dos assuntos que tratamos, procure também a secção «Leitura complementar» no capítulo correspondente do fmcbook para mais referências.
Dicas
- James Munkres: Comments on style
- Jean-Pierre Serre: How to write mathematics badly
- Don Knuth: Mathematical writing
- Paul Halmos: How to write mathematics
- Por que tantos livros? Qual é o melhor? Vale a pena ler esse excerto do livro Linear Algebra de Jänich.
Links
- NNG (Offline? Tente esse mirror também.)
- Lean & Lean web editor
- Haskell
- Minicurso TeX 2018.2
- Detexify
- Minicurso Unix 2019.2
- The Missing Semester of your CS Education
- Overleaf online (La)TeX editor/compilador
Tecnologias & ferramentas
Obs.: (Instalem e/ou criem uma conta para usar onde necessário.)
- PAPEL (um caderno para dedicar à disciplina) e LAPIS/CANETA.
- Zulip (leia o FAQ).
- O proof assistant Lean para algumas atividades (leia o FAQ).
- A linguagem de programação funcional Haskell para algumas atividades.
- Git (leia o FAQ).
- Muito recomendado mas não necessário: um sistema Unix (veja o minicurso Unix 2019.2).
- Muito recomendado mas não necessário: (neo)vim e Emacs.
- Pouco de (La)TeX (veja o minicurso TeX 2018.2). Online editor/compilador: Overleaf.
A parte IRI será auxiliada usando a linguagem de programação funcional Haskell e o proof assistant Lean. Usando uma linguagem de programação funcional é imediato implementar todas as suas definições para rodá-las no computador. Usando um proof assistant, formalizamos tanto as definições recursivas, quanto as demonstrações indutivas usando a mesma linguagem. (Mas o foco continua sendo o papel; não o computador!)
FAQs
Dynamic content
Provas
- Prova 2.1 de FMC1 de 2022.2 { censored , uncensored , answers , correções }
- Prova 2.2 de FMC1 de 2022.2 (NNG)
- Prova 2.3 de FMC1 de 2022.2 { censored , uncensored , answers , correções , quadro }
Sessões
Leia bem o FAQ sobre hw. Note também que:
- Homeworks são atribuidos também durante as aulas e no Zulip.
- Homeworks marcados assim são auxiliares; tente apenas se tu tem resolvido uma parte satisfatória dos outros.
IRI (1) [video]
- introdução
- um resumo da abordagem (axiomática) que usamos em IDMa
- especificação vs implementação; implementação-agnóstico
- a abordagem desta disciplina (IRI): mais contrastes de abordagem
- algebraic data types
- o tipo Nat: espectativas e 4 maneiras de definir um tipo de dados recursivamente
- sintaxe: o que queremos descrever
- o desafio dos «…» numa definição
- exemplo de chefe de programação sem noção comunicando pedido
- Naturais vs Nats; Números vs Numerais
- Linguagem vs Metalinguagem; Variáveis vs Metavariáveis
- «Nada mais»
- Regras de inferência e lida de cima para baixo e de baixo para cima
- Como mostrar que algo é um Nat
- arvores de inferência, folhas abertas e fechadas; regras e comandos
- casamento de padrão com expressão: primeiro encontro
- gramáticas e a notação BNF: nada demais!
- Mal entendido: «os inteiros que a gente conheceu»—Nope.
- Mal entendido: «uns inteiros são naturais»—Nope.
- type casting
- a aplicação duma função no seu argumento, e a inferncia de tipo relevante
- Tem como implementar os inteiros usando os naturais, e mais uns teasers
- Regras e arvores de inferência, comandos vs proposições
- Um exemplo de inferência: SSSO : Nat
- Definição recursiva vs tijolo
- um exemplo: fact : Nat → Nat
- Como traduzir uma linha sem premissas para código
hw
- Jogue o NNG. Tente completar o mais rápido possivel; sua entregá é a Prova 2.2. Veja o FAQ relevante também.
IRI (2) [video]
- ocorrências livres e ligadas de variáveis
- construtor vs função
- uns açúcares sintácticos
- uns preconceitos sobre funções e sua notação
- ocorrências ligadas e livres de variáveis
double : Nat → Nat
;id : Nat → Nat
- padrões de argumentos
- o presente da recursão
- Como calcular (modelo computacional)
- double 2 = ?
- valores canônicos
- casamento de padrões
- Duas maneiras de escrever cálculos
- A adiçaõ: (+)
- prefix, postfix, infix, mixfix
- Um cálculo e teorema: 2 + 3 ≟ 5
- Arvore sintáctica (Abstract Syntax Tree), parsing, (veja também: lexer)
- Precedência sintáctica
- Associatividade sintáctica
- Associatividade vs associatividade sintáctica: axiomas e especificação vs implementação
- Currificação
- como definir o
addFive
nível boss - Aplicação parcial
hw
- Calcule os:
double (double (S O))
double ((S O) + (S (S O)))
- Defina multiplicação e exponenciação.
- Olhando para as funçoẽs binárias e famosas que temos até agora (adição, multiplicação, exponenciação), perceba que tem um “padrão”. Use isso para definir a “próxima” operação. Denote por ⇈.
- Defina a função
Pd : Nat → Nat
de “predecessor”, onde consideramos que o predecessor de zero é o próprio zero mesmo: AVISO: a maioria das vezes que um aluno de 2022.1 usou aPd
em outras definições, estava errando - Defina a função
∸ : Nat → Nat → Nat
que comporta como subtração, mas caso que o resultado era pra ser negativo, retorna O mesmo. - Defina as funções:
fact : Nat → Nat
fib : Nat → Nat
dist : Nat → Nat → Nat
min : Nat → Nat → Nat
max : Nat → Nat → Nat
div : Nat × Nat → Nat × Nat
quot : Nat × Nat → Nat
rem : Nat × Nat → Nat
gcd : Nat × Nat → Nat
lcm : Nat × Nat → Nat
comb : Nat → Nat → Nat
perm : Nat → Nat → Nat
IRI (3,4) [video]
- construtor vs função
- D: multiplicação
- o uso de lemmas: m-idR, e-idR
- uma demonstração simples: (·)-idR
- ∀: como usar
- ∀: como atacar
- qual resultado incompleto é melhor?
- lazy vs strict
- estratégia de evaluação vs precedência de operador
- notação de aplicação de função por espaço:
f x
- acordos sintácticos sobre a aplicação-de-função: precedência, associatividade sintáctica à esquerda:
f x y z ≡ ((f x) y) z
, e os seus porquês - Θ. Associatividade da
(+)
- A disjunção escondida em cada Nat.
- ∃: como usar
- ∨: como usar
- tem como continuar a demonstração?
- escolhendo variáveis com «linhas»: x’, x’’, etc.
- igualdade entre Nats
- o problema que temos demonstrando esse teorema
hw
- (i) instale a Haskell no teu computador; (ii) Completa o getting started e o first steps do ghcup; (iii) configure teu editor (sendo ou um editor que presta (emacs ou neovim), ou o VS Code) para integrar com Haskell. Dúvidas nos
#programming
e#tech
, obviamente! - Implementa o
Nat
num módulo Haskell, junto com todas as funções que definimos até agora, incluindo os hw. Comece teu arquivo assim:module Nat where data Nat = O | S Nat deriving ( Eq , Show )
IRI (5): Nat [video]
- dois princípios sobre os construtores e os valores construidos
- escolhendo o padrão na direita duma equação para substituir na direção (←)
- o problema que temos demonstrando a (+)-associatividade
- A regra de inferência Ind-φ. (Onde φ : Nat → Prop.)
- Demonstração por indução
- A associatividade da (+): umas demonstrações por indução diferentes.
- Análise das duas melhores demonstrações da (+)-associatividade: legalzinho vs legalzão
- Inventar teoremas-propriedades sobre nossos programas
hw
- Resolva tudo na §«Demonstrando propriedades de naturais com indução»
- Asserte propriedades sobre teus programas do hw do IRI (2), e demonstre cada uma delas!
- Enuncie e demonstre que quaisquer fibonaccis consecutivos são coprimos.
IRI (6,7): Nat, Bool [video]
- currificação: versão currificada vs descurrificada da mesma função
- associatividade sintáctica
- inferência de tipo de aplicação de função
- conexão com uso de implicação; propositions-as-types
- prerequisito para perguntar sobre igualdade: mesmos tipos!
- Como implementar o tipo
Bool
(e suas operações) em termos deNat
: problemas - pra quem esse return 0 está retornando tal 0 nas mains dos programas?
- os booleanos precisam suas operações também
- booleanos em python e type casting
- a diferença entre a parte (e tipagem) estática e a parte (e tipagem) dinâmica
- type sistem e checagem de tipo vs evaluação de expressão para achar um valar
- O tipo
Bool
(de verdade) - Ordem: (≤) vs leq: mundo-objeto e mundo-meta
- corretude (soundness & completeness) de programas
(≤) : Nat → Nat → Prop
leq : Nat → Nat → Bool
- Relações vs funções-com-codomínio-Bool
- Como representar predicados sobre os naturais (Nat → Prop, Nat→Nat→Prop, etc.) como se fossem funções que retornam
Bool
. - A corretude da
leq
- internalização de conceito
- O uso de underscore nos padrões
- uma convenção sobre a ordem de equações numa definição recursiva
- Sobre funções parciais vs totais
- side effects (efeitos colaterais) e funções puras
- Type inference; como/quando aproveitar a inferência de tipos
- even e odd (pares e impares): como internalizar e como demonstrar corretude
ev, od : Nat → Bool
- treis maneiras diferentes de definir: precisando 3 equações; precisando o not; com recursão mútua
- recursão mútua
- backticks para notação infixa
- Como usar o underscore (_) como «variável sem nome» num padrão.
hw
- Defina e demonstre a corretude das funções:
leq : Nat → Nat → Bool
ev : Nat → Bool
od : Nat → Bool
isMul₃ : Nat → Bool
divides : Nat → Nat → Bool
congmod : ?
isZero : Nat → Bool
- Demonstre que a
(≤) : Nat → Nat → Prop
é: reflexiva; transitiva; antissimétrica; total - Demonstre que todo Nat é par ou ímpar.
- Defina os operadores booleanos.
- Como definarias uma função
if_then_else_ : Bool → Nat → Nat → Nat
? - Demonstre a corretude das funções definidas no hw do IRI (2).
- O lemma de divisão de Euclides para os Nats:
- enuncie
- demonstre
Prova 2.2
Complete o NNG.
IRI (8): Nat, Bool, Weekday, Unit, Empty, ListNat [video]
- Type synonym
- Desafio: Int parzinhos-de-Nats, vetores-de-Nats
- isBool : Nat → “Bool”
- O que acontece em linguagem que autoafirmam ter «tipos dinâmicos»
- Corretude de definição de função (programa): correção e completude
- Mais tipos de dados simples:
Weekday
- O tipo
Unit
com seu único habitánte/construtor:⋆ : Unit
- Quem é mesmo esse
void
? - Indução do Nat e quando não usar
- Q: faz sentido adicionar como açúcar sintáctico para o lem n m assumir papel de Prop? A: Não.
- Como implementar listas:
ListNat
- Os construtores
Empty
(ouNil
) eCons
- ListNat: sintaxe, açúcar e associatividade sintáctica
- Como escolher a ordem dos argumentos: aplicação parcial e currificação
- ListNat é um tipo recursivo
- Como representar a lista [2,0,8] com nosso tipo
- definindo a
length : ListNat → Nat
- Calculando o
length [3,2,0]
- Plicker: quantos construtores preciso para definir o tipo Int?
hw
- Implemente como Nats:
- os inteiros (já sabes a sua especificação pelo IDMa!)
- os parzinhos-de-Nats
- os vetores-de-Nats como Nat
- Implemente como novo tipos, tendo já definido o Nat:
- os inteiros
- os parzinhos-de-Nats
- os vetores-de-Nats como Nat
- Defina as:
length : ListNat → Nat
elem : Nat → ListNat → Bool
sum : ListNat → Nat
product : ListNat → Nat
(++) : ListNat → ListNat → ListNat
reverse : ListNat → ListNat
min : Nat → Nat → Nat
max : Nat → Nat → Nat
allEven : ListNat → Bool
anyEven : ListNat → Bool
allOdd : ListNat → Bool
anyOdd : ListNat → Bool
allZero : ListNat → Bool
anyZero : ListNat → Bool
addNat : Nat → ListNat → ListNat
multNat : Nat → ListNat → ListNat
expNat : Nat → ListNat → ListNat
enumFromTo : Nat → Nat → ListNat
enumTo : Nat → ListNat
take : Nat → ListNat → ListNat
drop : Nat → ListNat → ListNat
elemIndices : Nat → ListNat → ListNat
pwAdd : ListNat → ListNat → ListNat
pwMult : ListNat → ListNat → ListNat
isSorted : ListNat → Bool
filterEven : ListNat → ListNat
filterOdd : ListNat → ListNat
minimum : ListNat ⇀ Nat
maximum : ListNat ⇀ Nat
isPrefixOf : ListNat → ListNat → Bool
mix : ListNat → ListNat → ListNat
intersperse : Nat → ListNat → ListNat
- Defina as:
head : ListNat → Nat
tail : ListNat → ListNat
init : ListNat → ListNat
last : ListNat → Nat
- Defina a
(<) : Nat → Nat → Prop
e sua internalização, e demonstre a sua corretude.
IRI (9): Nat, Bool, Unit, Empty, ListNat [video]
- Definições de
sum : ListNat → Nat
eproduct : ListNat → Nat
- como escolher o valor certo para o
sum []
e oproduct []
- como escolher o valor certo para o
reverse
,append
, e concatenação binária(⧺)
- parenteses e convenções sintácticas do ␣
- mal-entendido entre função currificada-vs-descurrificada e notação infixa-vs-prefixa
- aplicação parcial e um cálculo relacionado
- «redex»
- a notação de “sections” de operadores binários
- um problema com as
head
etail
- um teaser sobre a soma de tipos
- Construtores vs Destrutores
- Corretude de programas sobre ListNat: propriedades que gostariamos de demonstrar
- Tentativa de demonstrar uma delas
- Como chegar aos principios de indução para os outros tipos
- O conceito de «respeitar/preservar uma propriedade».
- Do $\mathrm{Ind}^{\mathsf{Nat}}_{\varphi}$ para o $\mathrm{Ind}^{\mathsf{ListNat}}_{\varphi}$.
- Indução do
Bool
- Indução do
Unit
- Indução do
Empty
- Indução do
ListNat
- Indução do
- Como interpretar a indução e suas várias versões dos inteiros agora
- Uma maneira de pensar sobre indução: como separação-em-casos-com-extras
- Conexão entre recursão e indução
- Definição por recursão vs Demonstração por indução
- O presente de recursão vs o presente da indução
- Quantos quantificadores e por quê?
- Quantos destrutores e por quê?
hw
- Demonstre os teoremas (escolhe algo interessante para botar nos
??
)(∀xs,ys:ListNat) [ sum (xs ++ ys) = ?? ]
(∀xs,ys:ListNat) [ product (xs ++ ys) = ?? ]
(∀ℓ:ListNat) [ length (filterEven ℓ ++ filterOdd ℓ) = ?? ]
(∀ℓ:ListNat) [ reverse (filterEven ℓ) = ?? ]
(∀n:Nat)(∀ℓ:ListNat) [ length (addNat n ℓ) = ?? ]
(∀n:Nat)(∀ℓ:ListNat) [ sum (addNat n ℓ) = ?? ]
(∀n:Nat)(∀ℓ:ListNat) [ sum (multNat n ℓ) = ?? ]
(∀n:Nat)(∀ℓ:ListNat) [ product (multNat n ℓ) = ?? ]
(∀n:Nat)(∀ℓ:ListNat) [ product (expNat n ℓ) = ?? ]
(∀n:Nat)(∀ℓ:ListNat) [ isSorted (addNat n ℓ) = ?? ]
(∀ℓ:ListNat) [ isEven (product ℓ) = anyEven ℓ ]
(∀ℓ:ListNat) [ isEven (sum ℓ) = isEven (length (filterOdd ℓ)) ]
(∀ℓ:ListNat) [ isZero (sum ℓ) = ?? ]
(∀ℓ:ListNat) [ isZero (product ℓ) = ?? ]
(∀n,m:Nat)(∀ℓ:List Nat) [ addNat (n + m) ℓ = ?? ]
(∀n,m:Nat)(∀ℓ:List Nat) [ multNat (n · m) ℓ = ?? ]
- Demonstre também:
(∀xs,ys:ListNat) [ length (xs ++ ys) = ?? ]
(∀xs,ys:ListNat) [ reverse (xs ++ ys) = ?? ]
(∀n:Nat)(∀xs,ys:ListNat)[ addNat n (xs ++ ys) = ?? ]
(∀ℓ:ListNat) [ reverse (reverse ℓ) = ?? ]
(∀ℓ:ListNat) [ length (reverse ℓ) = ?? ]
- Associatividade da
(++)
[]
é uma(++)
-identidade
- Pense em mais propriedades, enuncie, e demonstre!
- (INTRO) Demonstre ou refute as leis seguintes (cada uma tem duas proposições independentes para investigar, e para cada uma tome o cuidado seguinte: se precisar saber que o tipo A é habitado, veja se e como isso afeta a tua resposta):
- (∀x:A)[φ ⇒ ψ(x)] ⇐≟⇒ φ ⇒ (∀x:A)[ψ(x)]
- (∀x:A)[φ(x) ⇒ ψ] ⇐≟⇒ (∀x:A)[φ(x)] ⇒ ψ
- (∃x:A)[φ ⇒ ψ(x)] ⇐≟⇒ φ ⇒ (∃x:A)[ψ(x)]
- (∃x:A)[φ(x) ⇒ ψ] ⇐≟⇒ (∃x:A)[φ(x)] ⇒ ψ
Prova 2.1 (IRI)
IRI (10a) [video]
- Polimorfismo de tipos, e o type constructor
List : Type → Type
- Construtores de tipos (type constructors) vs Construtores de valores (data constructors)
- type variables vs data variables
- polimorfismo: de
lengthNat : List Nat → Nat
paralength : List α → Nat
hw
- Generalize todas as funções dos hw 2022-11-04 e 2022-10-31 que envolvem
ListNat
para funções que envolvemList α
ou, se não for possível,List Nat
. - Defina as:
concat : List (List α) → List α
ifthenelse : Bool → α → α → α
and : List Bool → Bool
or : List Bool → Bool
splitAt : Nat → List α → (List α × List a)
zip : List α → List β → List (α × β)
unzip : List (α × β) → (List α × List β)
- Defina um tipo para conseguir uma resolução no problema de querer listas cujos membros podem ser
Nat
ouBool
. - Defina um tipo cujos habitantes serão usados para representar listas que garantam:
- ter tamanho ≥ 1 (
IList
) - ter tamanho par (
EList
) - ter tamanho ímpar (
OList
)
- ter tamanho ≥ 1 (
mais hw
- URGENTE! Continua (ou começa, pelamor de Curry) o hw do IRI (3,4), para incluir as funções que envolvem listas. O arquivo poderia começar assim:
{-# LANGUAGE GADTs, EmptyDataDecls #-} module IRI where data Nat where O :: Nat S :: Nat -> Nat deriving (Eq, Show) data Unit where Star :: Unit data Empty data List a where Nil :: List a Cons :: a -> List a -> List a deriving (Eq, Show)
IRI (10b, 11) [video]
- polimorfismo: função(ões)
id
- o tipo de
bottom
- Nats bottomosos (⊥, nats parciais, o nat infinito)
- mais um tira-gosto/teaser da idéia de propositions-as-types
- funções de ordem superior (higher-order functions)
- como agir se precisar numa lista ter naturais e booleanos: NatOrBool
- abstração de ordem superior: de
addNat : Nat → List Nat → List Nat
paramapNat : (Nat → Nat) → List Nat → List Nat
- abstração de ordem superior: de
mapNat : (Nat → Nat) → List Nat → List Nat
paramap : (α → β) → List α → List β
- a função map:
map : (α → β) → List α → List β
- a função filter: a
filter : (α → Bool) → List α → List α
- novas implementações das funções antigas
- Do $\mathrm{Ind}^{\mathtt{ListNat}}_{\varphi}$ para o $\mathrm{Ind}^{\mathtt{List~α}}_{\varphi}$.
- o
Maybe : Type → Type
- comparação dos tipos
Maybe (List α)
eList (Maybe α)
- Idéia ruim: usar um valor arbitrário para o
head []
- as versões não-gambiarrosas de
head
etail
- Resolução legal:
safeHead : List α → Maybe α
- Resolução legal:
safeTail : List α → Maybe (List α)
- desafio: como generalizar as sum, product, concat
- por que não podemos tipar a sum com List α → α?
- Uma find melhor que as gambiarras C’osas:
findFirst : α → List α → Maybe α
hw
- Gambiarra 1:
safeHead : ListNat → ListNat
- Gambiarra 2:
safeHead : ListNat → Bool × Nat
- Gambiarra 3:
defaultHead : Nat → ListNat → Nat
mais hw
- Defina as:
replicate : Nat → α → List α
map : (α → β) → List α → List β
filter : (α → Bool) → List α → List α
- a generalização
all
das:allZero
,allEven
,allOdd
- a generalização
any
das:anyZero
,anyEven
,anyOdd
- a generalização
pointwise
das:pwAdd
,pwMult
- a generalização
fold
das:sum
,product
,and
,or
,concat
- simplifique as definições antigas para aproveitar essas funções poderosas
takeWhile : (α → Bool) → List α → List α
dropWhile : (α → Bool) → List α → List α
head : List α → Maybe α
tail : List α → Maybe (List α)
init : List α → Maybe (List α)
last : List α → Maybe α
pick : Nat → List α → Maybe α
findFirst : α → List α → Maybe Nat
find : α → List α → List Nat
curry : ?
uncurry : ?
flip : ?
- Qual seria uma melhor tipágem para a
pw : (α → α → α) → List α → List α → List α
?
mais hw
- Descubra o
foldNat
: defina e mostre um uso dele
IRI (12,13) [video]
- os destrutores são, em geral, parciais; versões seguras
- de
NatOrBool
paraEither α β
- Produto de tipos: α × β
- Soma de tipos (coproduto): α + β
- O que usar para representar erros em vez de gambiarras tipo Strings e Números
- pw (zipWith, zip; veja sobre zipping)
- findFirst: primeira tentativa
- uma idéia sobre como resolver nosso problema:
(⟨$⟩)
/fmap
- uma outra idéia sobre como resolver nosso problema: pattern matching: match-expression
- de volta para a primeira idéia: fmap e Functors
- Functors, fmap, deriving ( Functor )
- Leis de Functor
- Abuso de List α para assumir papel de Maybe α
- Duas interpretações computacionais dos habitantes de List α
- Functorialidade do Either ε
- Composição de funções: (∘)
- programação tácita: point-free, point-less, …
- Como implementar os Ints usando Nats: igualdade
- Teaser sobre arvores
hw
- Demonstre a associatividade da
(∘)
- Defina tipos para cada um estilo de árvore que tu já viu ou imaginou
- Formulize os correspondentes princípios/regras de indução para cada um deles
- Mostre como cada um deles pode virar um Functors
- Demonstre as leis de Functor para o
List : Type → Type
com omap
que definimos:map id = id [functor law 1] map (f . g) = map f . map g [functor law 2]
- Demonstre:
(∀f:α→β)(∀p:β→Bool) [ filter p ∘ map f = map f ∘ filter (p ∘ f) ]
- Adivinha um lado direito certo e interessante, e demonstre:
take n xs ++ drop n xs = take m . take n = take m . drop n = drop m . take n = drop m . drop n = map g . map f = sum . map double = sum . map sum = sum . sort = map f . reverse = concat . map concat = filter p . map f = length . reverse = reverse . reverse =
- Quais das seguintes são válidas e quais não?
map f . take n =?= take n . map f map f . reverse =?= reverse .map f map f . sort =?= sort . map f reverse . concat =?= concat . reverse . map reverse filter p . concat =?= concat . map (filter p)
- Demonstre:
xs ++ (ys ++ zs) = (xs ++ ys) ++ zs [associatividade da (++)] length (xs ++ ys) = length xs + length ys filter p (xs ++ ys) = filter p xs ++ filter p ys map f (xs ++ ys) = map f xs ++ map f ys
- Demonstre:
sum (xs ++ ys) = sum xs + sum ys product (xs ++ ys) = product xs * product ys concat (xss ++ yss) = concat xss ++ concat yss
- Podemos definir uma generalização da
pw : (α → β → γ) → (F α → F β → F γ)
sabendo apenas que oF
possui umfmap
com qual ele se torna um Functor? - Implemente os racionais!
mais hw
- Na última aula percebemos que
Either
não tinha sequer chances de se candidatar para virar um Functor, poisEither
não é umType → Type
(mas sim umType → Type → Type
. Mesmo assim, conseguimos verificar que aplicando parcialmente oEither
num tipoε
só, chegamos mesmo noEither ε
que é mesmo umType → Type
, e logo tem chances de ser um Functor, e descubrimos qual seria afmap
certa pra isso (demonstre se não demonstrou—o que é pra demonstrar mesmo??). Aqui mais duas coisinhas que estão tambémType → Type → Type
: o próprio(→)
e o(×)
. Investigue para cada um deles, e para cada aplicação parcial dele, se pode ser munida com umfmap
para conseguir ser um Functor:(δ →) : Type → Type
(→ γ) : Type → Type
(α ×) : Type → Type
(× β) : Type → Type
IRI (14) [video]
- corretude: estipular e demonstrar propriedades dos nossos programas
- e sobre igualdade intensional entre funções
- uns tipos de arvores
- a map das listas e outras fmaps e as leis de Functor
- maneiras de escrever uso de indução é os detalhes possivelmente enganadores e implícitos
- a List com o map é um Functor: demonstração da 2a lei
- demonstração: a segunda lei de Functor para a map de List α
- Composição de Functors
- a propaganda mentirosa de «tipos dinâmicos» e a verdade decepcionante
- como funcionam linguagens de “tipos dinâmicos” e runtime errors
hw
- Prática para indução nos naturais: resolva o [Problem Set 2 de 2021.2][ps2-2021.2].
- Na aula de IDMb definimos uma
(·) : Real × Seq(Real) → Seq(Real)
em duas formas: implemente ambas em Haskell e demonstre a sua equivalência.
IRI (15,16) [video]
- Eficiência “por algebra”
- Eficiência “por indução”
- eliminando o (⧺) da
reverse
“por indução”
- eliminando o (⧺) da
- Arvores
- típos de árvores e umas funções relevantes
- size, nodes, depth, flatten, mapTree, foldTree, …
- Sintaxe vs semântica
- Numerais binários
- Um toque de expressões e ASTs
- BNF
- ArEx, ArExV
- semântica operacional
- semântica denotacional
- eval, step, bigstep
- funções fold: fold
hw
- Ordenação (sorting)
- Defina sozinhos os: merge sort; quick sort ;insertion sort
- ASTs
- Defina tipos para representar:
- expressões de aritmética sem variáveis:
- expressões de aritmética com variáveis;
- expressões de lógica proposicional
- Defina funções de
eval
estep
apropriadamente para cad um dos teus tipos
- Defina tipos para representar:
- Arvores
- Defina as:
nodesize : BinTree α → Nat
size : BinTree α → Nat
depth : BinTree α → Nat
leaves : BinTree α → List α
mapTree : ?
mirror : BinTree α → BinTree α
flatten : BinTree α → List α
findTree : α → GenTree α → List (List Nat)
sumTree : BinTree Nat → Nat
- Adivinhe uma conexão entre o número
size t
e o númeronodes t
: enuncie e demonstre! - Θ.
size t ≤ 2 ^ depth t
- Θ.
depth t ≤ length (flatten t)
- Verifique que tu passou EM & ME mesmo, reescrevendo o que demonstrou acima utilizando
log₂
- Defina o resto dos tipos de arvores discutidos nas aulas (peça detalhes no Zulip!)
- BinSearchTree α
- BinLabTree α β
- RoseTree α
- Demonstre como todos teus típos de árvores viram Functors
- Demonstre:
length ∘ flatten = ??
flatten ∘ mirror = ??
mirror ∘ mirror = ??
depth ∘ mirror = ??
depth ∘ fmap f = ??
fmap f ∘ mirror = ??
- Defina as:
- Eficiência “por indução” / parametro acumuladora: use a metodo que encontramos na aula eliminando o (⧺) da
reverse
para:- eliminá-lo da tua
flatten
- eliminá-lo da tua
leaves
- eliminá-lo da tua
- Folds & lists
- Defina uma foldT para os tipos de arvores que faz sentido definir
- Defina uma foldE para os tipos de Either
- Discuta qual deveria ser o tipo de uma
unfold
que cria listas a partir de outros valores; depois defina! reverse (xs ⧺ ys) = reverse ys ⧺ reverse xs
- Demonstre a lei de fusão do
foldr
que é: dado ??, temos:f ∘ foldr g a = foldr h b
Prova 2.3
Em um universo paralelo
- Expressões e ASTs
- Fórmulas de Lógica Proposicional
- Funções em fórmulas
- Recursão aninhada
- Ackermann
- Recursão para contagem