How to reverse a HVect in Idris?

六月ゝ 毕业季﹏ 提交于 2020-01-14 10:25:10

问题


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 rewrites 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 Vects 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!