【问题标题】:Idris - map an operation on a n-dimensional vectorIdris - 在 n 维向量上映射操作
【发布时间】:2017-11-29 17:11:23
【问题描述】:

我在Idris中定义了n维向量如下:

import Data.Vect

NDVect : (Num t) => (rank : Nat) -> (shape : Vect rank Nat) -> (t : Type) -> Type
NDVect Z     []      t = t
NDVect (S n) (x::xs) t = Vect x (NDVect n xs t)

然后我定义了以下函数,它将函数 f 映射到张量中的每个条目。

iterateT : (f : t -> t') -> (v : NDVect r s t) -> NDVect r s t'
iterateT {r = Z}   {s = []}    f v = f v
iterateT {r = S n} {s = x::xs} f v = map (iterateT f) v

但是当我尝试在以下函数中调用iteratorT 时:

scale : Num t => (c : t) -> (v : NDVect rank shape t) -> NDVect rank shape t
scale c v = iterateT (*c) v

我收到以下错误消息,说类型不匹配,这对我来说似乎很好

 When checking right hand side of scale with expected type
         NDVect rank shape t

 When checking argument v to function Main.iterateT:
         Type mismatch between
                 NDVect rank shape t (Type of v)
         and
                 NDVect r s t (Expected type)

         Specifically:
                 Type mismatch between
                         NDVect rank shape t
                 and
                         NDVect r s t             
         Specifically:
                 Type mismatch between
                         NDVect rank shape t
                 and
                         NDVect r s t

【问题讨论】:

标签: idris


【解决方案1】:

我也一直想知道如何在 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

并实现map如下:

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

不幸的是,拥有所有类型构造函数会让事情变得有点难看。我很想知道是否有更清洁的方法来解决这个问题。

编辑:

这是一个略短的类型签名,它没有明确编码类型中的张量等级:

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)

【讨论】: