Plus vs S in a function type

荒凉一梦 提交于 2019-12-05 23:59:33

Why does x :: xs : Vect (n + 1) a lead to a type error?

(+) is defined by induction on its first argument so n + 1 is stuck (because n is a stuck expression, a variable in this case).

(::) is defined with the type a -> Vect m a -> Vect (S m) a.

So Idris needs to solve the unification problem n + 1 =? S m and because you have a stuck term vs. an expression with a head constructor these two things simply won't unify.

If you had written 1 + n on the other hand, Idris would have reduced that expression down to S n and the unification would have been successful.

Why does xs ++ ys : Vect (n + m) a succeeds?

(++) is defined with the type Vect p a -> Vect q a -> Vect (p + q) a.

Under the assumption that xs : Vect n a and ys : Vect m a, you will have to solve the constraints:

  • Vect n a ?= Vect p a (xs is the first argument passed to (++))
  • Vect m a ?= Vect q a (ys is the first argument passed to (++))
  • Vect (n + m) a ?= Vect (p + q) a (xs ++ ys is the result of append)

The first two constraints lead to n = p and m = q respectively which make the third constraint hold: everything works out.

Consider append : Vect n a -> Vect m a -> Vect (m + n) a.

Notice how I have swapped the two arguments to (+) in this one. You would then be a situation similar to your first question: after a bit of unification, you would end up with the constraint m + n ?= n + m which Idris, not knowing that (+) is commutative, would'nt be able to solve.

Solutions? Work arounds?

Whenever you can it is infinitely more convenient to have a function defined using the same recurrence pattern as the computation that happens in its type. Indeed when that is the case the type will be simplified by computation in the various branches of the function definition.

When you can't, you can rewrite proofs that two things are equal (e.g. that n + 1 = S n for all n) to adjust the mismatch between a term's type and the expected one. Even though this may seem more convenient than refactoring your code to have a different recurrence pattern, and is sometimes necessary, it usually is the start of path full of pitfalls.

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