问题
I'm new to Irdis. Is it possible to reverse a HVect? If I call reverse on a HVect [String, Int]
it should return a HVect [Int, String]
and if I call reverse on a HVect [String, Int, Day]
it should return a HVect [Day, Int, String]
.
I tried to reuse Data.Vect.reverse
(Gist)
module reverse_hvect
import Data.HVect
reverse : HVect ts -> HVect (reverse ts)
reverse [] = []
reverse (x::xs) = (reverse xs) ++ [x]
but I get
Type checking .\reverse_hvect.idr
reverse_hvect.idr:7:9:When checking right hand side of reverse_hvect.reverse with expected type
HVect (reverse (t :: ts))
Type mismatch between
HVect (Data.Vect.reverse, go Type k ts [] ts ++ [t]) (Type of reverse xs ++ [x])
and
HVect (Data.Vect.reverse, go Type (S k) (t :: ts) [t] ts) (Expected type)
Specifically:
Type mismatch between
Data.Vect.reverse, go Type k ts [] ts ++ [t]
and
Data.Vect.reverse, go Type (S k) (t :: ts) [t] ts
Holes: reverse_hvect.reverse
Since Data.Vect.reverse
uses an inner function go
with an accumulator, I wrote my own Vect.reverse
with the same structure as my HVect.reverse
(Gist)
module reverse_hvect
import Data.Vect
import Data.HVect
myReverse : Vect n a -> Vect n a
myReverse [] = []
myReverse {n = S k} (x::xs) = rewrite plusCommutative 1 k in (myReverse xs) ++ [x]
reverse : HVect ts -> HVect (myReverse ts)
reverse [] = []
reverse (x::xs) = (reverse xs) ++ [x]
but I get another error
Type checking .\reverse_hvect.idr
reverse_hvect.idr:12:9:When checking right hand side of reverse_hvect.reverse with expected type
HVect (myReverse (t :: ts))
Type mismatch between
HVect (myReverse ts ++ [t]) (Type of reverse xs ++ [x])
and
HVect (replace (sym (replace (sym (replace (sym (plusZeroRightNeutral k)) Refl)) (replace (sym (plusSuccRightSucc k 0)) Refl))) (myReverse ts ++ [t])) (Expected type)
Specifically:
Type mismatch between
myReverse ts ++ [t]
and
replace (sym (replace (sym (replace (sym (plusZeroRightNeutral k)) Refl)) (replace (sym (plusSuccRightSucc k 0)) Refl))) (myReverse ts ++ [t])
Holes: reverse_hvect.reverse
回答1:
user3237465's answer in Idris:
import Data.Vect
import Data.HVect
nreverse : Nat -> Nat
nreverse Z = Z
nreverse (S n) = nreverse n + 1
vreverse : Vect n a -> Vect (nreverse n) a
vreverse [] = []
vreverse (x :: xs) = vreverse xs ++ [x]
hreverse : HVect ts -> HVect (vreverse ts)
hreverse [] = []
hreverse (x :: xs) = hreverse xs ++ [x]
You had the right idea with the same structures in the different reverses, but tried the more difficult structure.
回答2:
Having rewrite
s at the type level is a bad idea. I don't have the Idris type checker, but it should be straightforward to adapt this Agda code:
open import Data.Nat.Base
open import Data.Vec hiding (reverse)
infixr 5 _∷ₕ_ _++ₕ_
nreverse : ℕ -> ℕ
nreverse 0 = 0
nreverse (suc n) = nreverse n + 1
vreverse : ∀ {n α} {A : Set α} -> Vec A n -> Vec A (nreverse n)
vreverse [] = []
vreverse (x ∷ xs) = vreverse xs ++ (x ∷ [])
data HList : ∀ {n} -> Vec Set n -> Set where
[]ₕ : HList []
_∷ₕ_ : ∀ {n A} {As : Vec Set n} -> A -> HList As -> HList (A ∷ As)
_++ₕ_ : ∀ {n m} {As : Vec Set n} {Bs : Vec Set m} -> HList As -> HList Bs -> HList (As ++ Bs)
[]ₕ ++ₕ ys = ys
(x ∷ₕ xs) ++ₕ ys = x ∷ₕ xs ++ₕ ys
reverseₕ : ∀ {n} {As : Vec Set n} -> HList As -> HList (vreverse As)
reverseₕ []ₕ = []ₕ
reverseₕ (x ∷ₕ xs) = reverseₕ xs ++ₕ (x ∷ₕ []ₕ)
I.e. you just need one another reverse
in the tower of reverses, namely the one that "reverses" a number.
BTW, reverse for Vect
s in the Idris library is more involved than it should be. Here is a rewrite-free version.
来源:https://stackoverflow.com/questions/36430390/how-to-reverse-a-hvect-in-idris