agda学习笔记依赖函数/隐式参数/模式匹配

发现一个非常不错的资源:

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 没有定义

所以遇到非法的情况直接写 () 然后不写下去

这么做相当于防止访问到非法的地址

 

原文地址:https://www.cnblogs.com/liankewei/p/15572771.html