0

I'd like to determine all sub-dimensions of a HVect as a HVect.

Example:

import Data.HVect

myHVect : HVect [Int, String, List Nat]
myHVect = [42, "text", [1, 2, 3]]

subDimensions : HVect [ HVect [Int], HVect [Int, String], HVect [Int, String, List Nat] ]
subDimensions = subDimHVect myHVect
-- [ [42], [42, "text"], [42, "text", [1, 2, 3]] ]

My approach looks like this:

subDimHVect v = subDimHVect' [] [] v
  where
    subDimHVect' result _ [] = result
    subDimHVect' result lastDim (x::xs) =
      let nextDim = lastDim ++ [x] in
      subDimHVect' (result ++ [nextDim]) nextDim xs

but I don't know how to type subDimHVect and subDimHVect' correctly. Implementation seems to be fine:

Manual Calculation of the example:

subDimHVect [42, "text", [1, 2, 3]]
  = subDimHVect' [] [] [42, "text", [1, 2, 3]]
  = subDimHVect' [[42]] [42] ["text", [1, 2, 3]]
  = subDimHVect' [[42], [42, "text"]] [42, "text"] [[1, 2, 3]]
  = subDimHVect' [[42], [42, "text"], [42, "text", [1, 2, 3]]] [42, "text", [1, 2, 3]] []
  = [[42], [42, "text"], [42, "text", [1, 2, 3]]]

I'm quite new to Idris and dependent types. I would appreciate some help to find the missing type signatures.

Edit: I found another approach that might be easier to type, even though I couldn't figure the type out either (definition of reverse):

subDimHVect v = reverse (subDimHVect' (reverse v))
  where
    subDimHVect' [] = []
    subDimHVect' (x::xs) = [(x::xs)] ++ (subDimHVect' xs)

Manual Calculation of the example (using the second approach):

subDimHVect [42, "text", [1, 2, 3]]
  = reverse (subDimHVect' (reverse [42, "text", [1, 2, 3]]))
  = reverse (subDimHVect' [[1, 2, 3], "text", 42])
  = reverse ([ [[1, 2, 3], "text", 42] ] ++ (subDimHVect' ["text", 42]))
  = reverse ([ [[1, 2, 3], "text", 42] ] ++ [ ["text", 42] ] ++ (subDimHVect' [42]))
  = reverse ([ [[1, 2, 3], "text", 42] ] ++ [ ["text", 42] ] ++ [ [42] ] ++ (subDimHVect' []))
  = reverse ([ [[1, 2, 3], "text", 42] ] ++ [ ["text", 42] ] ++ [ [42] ] ++ [])
  = reverse ([ [[1, 2, 3], "text", 42], ["text", 42], [42] ])
  = [ [42], [42, "text"], [42, "text", [1, 2, 3]] ]
Community
  • 1
  • 1
maiermic
  • 4,764
  • 6
  • 38
  • 77

1 Answers1

2

First attempt:

subDimensions : HVect ts -> HVect xs

The xs would be treated as an implicit argument (as in subDimensions : {ts : Vect n Type} -> {xs : Vect k Type} -> HVect ts -> HVect xs), so the caller could say how the resulting HVect will look like. That's not right. We could create the xs alongside (see this answer's history if you find out how):

subDimensions : HVect {k} ts -> (xs : (Vect k Type) ** HVect xs)

However, a

subDimensions : HVect ts -> HVect (dimType ts)

would be more useful. Following your second attempt, we can create

dimType : Vect k Type -> Vect k Type
dimType [] = []
dimType (x :: xs) = (HVect (vreverse (x::xs))) :: dimType xs

and following the structure of the type, we define the helper subDimensions':

subDimensions' : HVect ts -> HVect (dimType ts)
subDimensions' [] = []
subDimensions' (x :: xs) = (hreverse (x :: xs)) :: subDimensions' xs

and the wrapper

subDimensions : HVect ts -> HVect (vreverse (dimType (vreverse ts)))
subDimensions xs = hreverse $ subDimensions' $ hreverse xs

(for the definition of hreverse and vreverse see here)

Community
  • 1
  • 1
xash
  • 3,702
  • 10
  • 22