3

I am compiling the following simple program using Idris2.

import Data.Fin

%default total

negate : {k:_} -> Fin k -> Fin k
subt : {k:_} -> Fin k -> Fin k -> Fin k
add : {k:_} -> Fin k -> Fin k -> Fin k

mult : {k:_} -> Fin k -> Fin k -> Fin k
mult FZ b = FZ
mult (FS a) b = add b $ mult (weaken a) b

However, the compiler spits an error:

Error: mult is not total, possibly not terminating due to recursive
path Main.mult -> Main.mult -> Main.mult

Isn't the recursive call on input a which is smaller than (FS a)? Why is the totality check failing?

Thanks!

1 Answers1

0

I don't know why the compiler doesn't realize that weaken a is smaller than FS a, although I suspect that the problem is weaken.

You can work around it by asserting that weaken a is smaller than FS a:

module Misc

import Data.Fin

%default total

add : Fin k -> Fin k -> Fin k
add a b = ?add_rhs

mult : Fin k -> Fin k -> Fin k
mult FZ _ = FZ
mult a@(FS a') b = add b $ mult (assert_smaller a (weaken a')) b

Do note that under the usual definition of addition and multiplication on integers, the result could be larger than k. I assume your add implementation will take care of this.

shadowtalker
  • 12,529
  • 3
  • 53
  • 96
  • 1
    Thanks for the reply. But I am interested in a solution without assert_smaller. I found a way to circumvent this, by avoid using `weaken` altogether. – haskell looks great Sep 09 '22 at 01:57
  • 1
    @haskelllooksgreat that sounds good, feel free to post an answer to your own question! Self-answers are allowed and encouraged here. – shadowtalker Sep 09 '22 at 02:14