证明任意嵌套的 Vect 别名是可显示的

Prove arbitrarily-nested Vect alias is showable

多年来,我一直在努力弄清楚如何为我的 Tensor 类型实现 ShowTensor 是围绕单个值或任意嵌套 Vect 个值

的薄包装器
import Data.Vect

Shape : Nat -> Type
Shape rank = Vect rank Nat

array_type: (shape: Shape rank) -> (dtype: Type) -> Type
array_type [] dtype = dtype
array_type (d :: ds) dtype = Vect d (array_type ds dtype)

data Tensor : (shape: Shape rank) -> (dtype: Type) -> Type where
  MkTensor : array_type shape dtype -> Tensor shape dtype

Show dtype => Show (Tensor shape dtype) where
  show (MkTensor x) = show x

我明白了

When checking right hand side of Prelude.Show.Main.Tensor shape dtype implementation of Prelude.Show.Show, method show with expected type
        String

Can't find implementation for Show (array_type shape dtype)

这是可以理解的,因为 array_type 并非微不足道。我相信它应该 show 可用,因为我可以 show 在 REPL 中高度嵌套 Vect,只要它们的元素是 Show。我想 Idris 只是不知道它是一个任意嵌套的 Vect.

如果我在 rank/shape 上引入一些隐式参数和大小写拆分,我会有所收获

Show dtype => Show (Tensor {rank} shape dtype) where
  show {rank = Z} {shape = []} (MkTensor x) = show x  -- works
  show {rank = (S Z)} {shape = (d :: [])} (MkTensor x) = show x  -- works
  show {rank = (S k)} {shape = (d :: ds)} (MkTensor x) = show x  -- doesn't work

我可以无限期地将它扩展到越来越高的级别 明确地,其中 RHS 始终只是 show x,但我不知道如何获得这是对所有级别进行类型检查。我猜想需要一些递归的东西。

EDIT 明确地说,我想知道如何通过使用 Idris 的 Show for Vects 实现来做到这一点。我想避免自己手动构建实现。

您走在正确的轨道上:您可以通过在嵌套向量上编写递归函数,然后在 Show 实现中将其提升为您的 Tensor 类型来实现:

showV : Show dtype => array_type shape dtype -> String
showV {rank = 0} {shape = []} x = show x
showV {rank = (S k)} {shape = d :: ds} xs = combine $ map showV xs
  where
    combine : Vect n String -> String
    combine ss = "[" ++ concat (intersperse ", " . toList $ ss) ++ "]"

Show dtype => Show (Tensor {rank} shape dtype) where
  show (MkTensor x) = showV x

示例:

λΠ> show $ the (Tensor [1, 2, 3] Int) $ MkTensor [[[1, 2, 3], [4, 5, 6]]]
"[[[1, 2, 3], [4, 5, 6]]]"

如果您想通过 Show (Vect n a) 实现,您也可以通过定义一个 Show 实现来实现,该实现要求向量有一个 Show

import Data.Vect
import Data.List

Shape : Nat -> Type
Shape rank = Vect rank Nat

array_type: (shape: Shape rank) -> (dtype: Type) -> Type
array_type [] dtype = dtype
array_type (d :: ds) dtype = Vect d (array_type ds dtype)

data Tensor : (shape: Shape rank) -> (dtype: Type) -> Type where
  MkTensor : array_type shape dtype -> Tensor shape dtype

Show (array_type shape dtype) => Show (Tensor {rank} shape dtype) where
  show (MkTensor x) = show x

对于 shape 的所有选择,Show (array_type shape dtype) 约束将减少到 Show dtype,例如这有效:

myTensor : Tensor [1, 2, 3] Int
myTensor = MkTensor [[[1, 2, 3], [4, 5, 6]]]
*ShowVect> show myTensor 
"[[[1, 2, 3], [4, 5, 6]]]" : String