Unificación algoritmo infiere demasiado tipos de hormigones
-
22-12-2019 - |
Pregunta
Yo estaba tratando de crear Tuplas de tamaño n en Idris:
module NTuple
data Tuple : Vect n Type -> Type where
EmptyTuple : Tuple Nil
TupleItem : a -> Tuple types -> Tuple (a :: types)
mapN : {types : Vect n Type} -> (i : Fin (S n)) -> (a -> b) -> Tuple (insertAt i a types) -> Tuple (insertAt i b types)
mapN fZ f (TupleItem x xs) = TupleItem (f x) xs
mapN (fS i) f (TupleItem x xs) = TupleItem x (mapN i f xs)
Pero estoy recibiendo este error en la última línea:
When elaborating left hand side of mapN: When elaborating an application of NTuple.mapN: Can't unify Tuple (a :: types) with Tuple (insertAt (fS i) a types) Specifically: Can't unify a :: types with insertAt (fS i) a types
Hay una manera de hacer que esta función trabaje?
Solución
El problema es que insertAt (FS i) a types
no puede ser reducido sin saber nada acerca de types
.Si lo sabía types = t :: ts
a continuación, se puede reducir a t :: insertAt i ts
.
Pero en el segundo caso de mapN
, nos ¿ saber que types
es exactamente de que forma:
- Nuestro primer argumento es
FS i
- Lo que implica
n = S m
para algunosm
... - Lo que significa que nuestro implícito
types
el argumento tiene el tipoVect (S m) Type
- Lo que significa que es de la forma
t :: ts
!
Una vez que este a Idris, es feliz para reducir insertAt (FS i) a types
y así, su código typechecks:
mapN : {types : Vect n Type} -> (i : Fin (S n)) -> (a -> b) -> Tuple (insertAt i a types) -> Tuple (insertAt i b types)
mapN FZ f (TupleItem x xs) = TupleItem (f x) xs
mapN {types = _ :: _} (FS i) f (TupleItem x xs) = TupleItem x (mapN i f xs)
mapN {types = []} (FS i) _ _ = absurd i
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow