I've been trying to figure out how to implement Show
for my Tensor
type for ages. Tensor
is a thin wrapper round either a single value, or arbitrarily-nested Vect
s of values
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
I get
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)
which is understandable given array_type
's not trivial. I believe that it should be show
able, as I can show
highly-nested Vect
s in the REPL as long their elements are Show
. I guess Idris just doesn't know it's an arbitrarily nested Vect
.
If I pull in some implicit parameters and case split on rank/shape, I get somewhere
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
and I can indefinitely expand this to higher and higher rank explicitly, where the RHS is always just show x
, but I can't figure out how to get this to type check for all ranks. I'd guess some recursive thing is required.
EDIT to be clear, I want to know how to do this by using Idris' implementation of Show
for Vect
s. I want to avoid having to construct an implementation manually myself.
If you want to go via the Show (Vect n a)
implementations, you can do that as well, by defining a Show
implementation that requires that there is a Show
for the vector:
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
For all choices of shape
, the Show (array_type shape dtype)
constraint will reduce to Show dtype
, so e.g. this works:
myTensor : Tensor [1, 2, 3] Int
myTensor = MkTensor [[[1, 2, 3], [4, 5, 6]]]
*ShowVect> show myTensor
"[[[1, 2, 3], [4, 5, 6]]]" : String