Plus vs S in a function type

走远了吗. 提交于 2019-12-22 10:43:28

问题


The following declaration of vector cons

cons : a -> Vect n a -> Vect (n + 1) a
cons x xs = x :: xs

fails with the error

Type mismatch between
                S n
        and
                plus n 1

while the following vector append compiles and works

append : Vect n a -> Vect m a -> Vect (n + m) a
append xs ys = xs ++ ys

Why type-level plus is accepted for the second case but not for the first. What's the difference?


回答1:


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.



来源:https://stackoverflow.com/questions/45744130/plus-vs-s-in-a-function-type

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