0

I want to write a function that accepts arbitrarily-nested Vects whose final elements are of a limited set of types incl. Double and Integer (the "dtype"), and the function is aware of how many Vects there were, and the size of each (i.e. the "shape").

For example, if my function's called const, I want const 0.0 and const [[0.0], [1.0]] to compile, and the type-checker know that the first has no Vects, and the second has two, with lengths 2 and 1. And I don't want const [["foo"], ["bar"]] to compile.

What I've tried

  • defining a type alias for nested vects and using namespaces for overloads
Array : (shape : Vect rank Nat) -> Type -> Type
Array [] ty = ty
Array (d :: ds) ty = Vect d (Array ds ty)

namespace double
  const : Array shape Double -> Foo shape Double

namespace integer
  const : Array shape Integer -> Foo shape Integer

but because this is slightly backwards (the compiler has to infer the type from the return type not argument of const), this has trouble inferring the types (even for simple cases like const 0.0) in ambiguous contexts.

  • defining an interface to keep track of the shape
interface Array ty where
  rank : Nat
  shape : Vect rank Nat
  dtype : Type

Array Double where  -- same for other types
  rank = 0
  shape = []
  dtype = Double

{len : Nat} -> Array ty => Array (Vect len ty) where
  rank = 1 + rank {ty}
  shape = len :: shape {ty}
  dtype = dtype {ty}

const : Array ty => ty -> Foo (shape {ty}) (dtype {ty})

but this doesn't work because Idris doesn't disambiguate between Data.Vect.:: and Prelude.:: in const [0.0], even though I've only implemented Array for Vect not List.

joel
  • 6,359
  • 2
  • 30
  • 55
  • Would something like `const (the (Vec 1 Double) [0.0])` work for your use case, or would it be too cumbersome in most cases? – Cactus Jun 04 '21 at 04:13
  • @Cactus it would be too cumbersome – joel Jun 04 '21 at 12:21
  • In Haskell I would solve this by making the `Array (Vect len ty)` instance more generic to `(f ~ Vect len) => Array (f ty)`. Not sure what the Idris syntax for this is. – Sjoerd Visscher Jun 06 '21 at 15:50
  • @SjoerdVisscher can you maybe say what that means in words? – joel Jun 06 '21 at 16:21
  • @joel In `const [0.0]` Idris doesn't know if you mean `Vect Double` or `List Double`, but it does know that it is `f Double` for some `f`. So an instance `Array (f ty)` would match. And then the constraint on that instance says that `f` should be `Vect`. – Sjoerd Visscher Jun 07 '21 at 09:19

0 Answers0