证明任意嵌套的 Vect 别名是可显示的
Prove arbitrarily-nested Vect alias is showable
多年来,我一直在努力弄清楚如何为我的 Tensor
类型实现 Show
。 Tensor
是围绕单个值或任意嵌套 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 Vect
s 实现来做到这一点。我想避免自己手动构建实现。
您走在正确的轨道上:您可以通过在嵌套向量上编写递归函数,然后在 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
多年来,我一直在努力弄清楚如何为我的 Tensor
类型实现 Show
。 Tensor
是围绕单个值或任意嵌套 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 Vect
s 实现来做到这一点。我想避免自己手动构建实现。
您走在正确的轨道上:您可以通过在嵌套向量上编写递归函数,然后在 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