统一算法推断出太具体的类型

时间:2014-07-31 15:39:01

标签: idris

我试图在Idris中创建大小为n的元组:

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)

但是我在最后一行收到了这个错误:

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

有没有办法让这个功能起作用?

1 个答案:

答案 0 :(得分:2)

问题是insertAt (FS i) a types如果不了解types,就无法减少types = t :: ts。如果我们知道t :: insertAt i ts,则可以将其缩减为mapN

但是在types的第二个案例中,我们知道FS i完全符合这种形式:

  1. 我们的第一个论点是n = S m
  2. 暗示m某些types ...
  3. 意味着我们的隐式Vect (S m) Type参数的类型为t :: ts
  4. 这意味着它的格式为insertAt (FS i) a types
  5. 一旦我们向Idris指出这一点,我们很乐意减少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 因此您的代码类型检查:

    {{1}}