发现一个非常不错的资源:
https://agda-zh.github.io/PLFA-zh/
良心翻译啊,界面也简单明了
1.优先级
infixl 6 _+_
infixr 7 _*_
定义加法是左结合的 优先级6
定义乘法是右结合的 优先级7
依赖函数 (Dependent Functions)
概念有点抽象...指的是 B 的类型依赖于某一个其它类型的值 a
比如说 a 是个 Nat ,a = 5 ,B 是 int [5] ,那么就认为 B 依赖 a
好像不太恰当,将就吧
identity : (A : Set) -> (a : A) -> A
identity A x = x
apply : (A : Set) -> (B : A -> Set) -> ((x : A) -> B x) -> (a : A) -> B a
apply A B f a = f a
(x : A) -> B x 表示接受 A 类型的输入并返回 B x 类型的输出
apply 中的 a 可以看成 A 类型的一个变量
隐式参数
上文的 identity 和 apply 可以改写如下
id : {A : Set} -> A -> A
id x = x
apply : {A : Set}{B : A -> Set} -> ((x : A) -> B x) -> (a : A) -> B a
apply f a = f a
相当于底下实现的时候就不声明类型了,让编译器自己推导
_o_ : {A : Set} -> {B : A -> Set} -> {C : (x : A) -> B x -> Set} ->
(f : {x : A}(y : B x) -> C x y)(g : (x : A) -> B x)(x : A) -> C x (g x)
(f o g) x = f (g x)
函数的复合
数据类型族(Data type family)
data Vec (A : Set) : Nat -> Set where
[] : Vec A zero
_::_ : {n : Nat} -> A -> Vec A n -> Vec A (suc n)
head : {A : Set}{n : Nat} -> Vec A (suc n) -> A
head (x :: xs) = x
vmap : {A B : Set} {n : Nat} -> (A -> B) -> Vec A n -> Vec B n
vmap f [] = []
vmap f (x :: xs) = f x :: vmap f xs
data List (A : Set) : Set where
[] : List A
_::_ : A -> List A -> List A
map : {A B : Set} -> (A -> B) -> List A -> List B
map f [] = []
map f (x :: xs) = f x :: map f xs
_++_ : {A : Set} -> List A -> List A -> List A
[] ++ ys = ys
(x :: xs) ++ ys = x :: (xs ++ ys)
这个就和 Haskell 差不多了
点模式匹配:静态可推导信息
data Vec2 (A : Set) : Nat -> Set where
nil : Vec2 A zero
cons : (n : Nat) -> A -> Vec2 A n -> Vec2 A (suc n)
vmap2 : {A B : Set}(n : Nat) -> (A -> B) -> Vec2 A n -> Vec2 B n
vmap2 .zero f nil = nil
vmap2 .(suc n) f (cons n x xs) = cons n (f x) (vmap2 n f xs)
vmap3 : {A B : Set}(n : Nat) -> (A -> B) -> Vec2 A n -> Vec2 B n
vmap3 zero f nil = nil
vmap3 (suc n) f (cons .n x xs) = cons n (f x) (vmap3 n f xs)
我现在还太懂(
按同学说来是 check 一下?
似乎没有什么大用
助教说 允许两个模式绑定同一个变量
荒谬模式匹配
data Fin : Nat -> Set where
fzero : {n : Nat} -> Fin (suc n)
fsuc : {n : Nat} -> Fin n -> Fin (suc n)
magic : {A : Set} -> Fin zero -> A
magic ()
_!_ : {n : Nat}{A : Set} -> Vec A n -> Fin n -> A
[] ! ()
(x :: xs) ! fzero = x
(x :: xs) ! (fsuc i) = xs ! i
怪异起来了
Fin n 定义的是小于 n 的数字
Fin zero 没有定义
所以遇到非法的情况直接写 () 然后不写下去
这么做相当于防止访问到非法的地址