我也一直想知道如何在 Idris 中表达 n 维向量(即张量)。我尝试了问题中的类型定义,但遇到了各种问题,所以我表达了NDVect
作为数据类型的函数:
data NDVect : (rank : Nat) -> (shape : Vect rank Nat) -> Type -> Type where
NDVZ : (value : t) -> NDVect Z [] t
NDV : (values : Vect n (NDVect r s t)) -> NDVect (S r) (n::s) t
并实现了地图如下:
nmap : (t -> u) -> (NDVect r s t) -> NDVect r s u
nmap f (NDVZ value) = NDVZ (f value)
nmap f (NDV values) = NDV (map (nmap f) values)
现在可以执行以下操作:
*Main> NDVZ 5
NDVZ 5 : NDVect 0 [] Integer
*Main> nmap (+4) (NDVZ 5)
NDVZ 9 : NDVect 0 [] Integer
*Main> NDV [NDVZ 1, NDVZ 2, NDVZ 3]
NDV [NDVZ 1, NDVZ 2, NDVZ 3] : NDVect 1 [3] Integer
*Main> nmap (+4) (NDV [NDVZ 1, NDVZ 2, NDVZ 3])
NDV [NDVZ 5, NDVZ 6, NDVZ 7] : NDVect 1 [3] Integer
不幸的是,拥有所有类型构造函数会让事情变得有点难看。我很想知道是否有更干净的方法来解决这个问题。
Edit:
这是一个稍微短一点的类型签名,它没有显式编码类型中的张量等级:
data NDVect : (shape : List Nat) -> Type -> Type where
NDVZ : (value : t) -> NDVect [] t
NDV : (values : Vect n (NDVect s t)) -> NDVect (n::s) t
nmap : (t -> u) -> (NDVect s t) -> NDVect s u
nmap f (NDVZ value) = NDVZ (f value)
nmap f (NDV values) = NDV (map (nmap f) values)