Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Totality checker issue when inductive data-type use is in a parameter of another data-type #3661

Open
Termina1 opened this issue Feb 14, 2017 · 4 comments

Comments

@Termina1
Copy link
Contributor

Termina1 commented Feb 14, 2017

mutual
  data First = FirstSimple | FirstSecond Second
  data Second = SecondSimple | SecondFirst (List First)

mutual
  calculate : First -> Nat
  calculate FirstSimple = 1
  calculate (FirstSecond x) = calculateSecond x
    where
      calculateSecond : Second -> Nat
      calculateSecond SecondSimple = 2
      calculateSecond (SecondFirst xs) = calculateMany xs


  calculateMany : List First -> Nat
  calculateMany xs = foldl (\acc, el => (calculate el) + acc) 0 xs

Idris totality checker thinks the function calculate is not total, however if I change the last line using foldl:

mutual
  data First = FirstSimple | FirstSecond Second
  data Second = SecondSimple | SecondFirst (List First)

mutual
  calculate : First -> Nat
  calculate FirstSimple = 1
  calculate (FirstSecond x) = calculateSecond x
    where
      calculateSecond : Second -> Nat
      calculateSecond SecondSimple = 2
      calculateSecond (SecondFirst xs) = calculateMany xs


  calculateMany : List First -> Nat
  calculateMany xs = foldl (+) 0 (map calculate xs)

Idris assumes calculate is total, what's the reason. Could you explain is it a bug or expected behaviour?

@anton-trunov
Copy link

anton-trunov commented Feb 19, 2017

I translated the above mutual inductive definition into a type family and can confirm that the totality checker doesn't see the calculate function as total. Tested with Idris Version 0.99-git:6f46ba0e. Incidentally, Coq recognizes the function as total.

data FS : (switch : Bool) -> Type where
  FirstSimple : FS False
  FirstSecond : FS True -> FS False
  SecondSimple : FS True
  SecondFirst : List (FS False) -> FS True

calculate : FS b -> Nat
calculate FirstSimple = 1
calculate (FirstSecond x) = calculate x
calculate SecondSimple = 2
calculate (SecondFirst xs) = sum $ map calculate xs

@ahmadsalim
Copy link

Thanks for the bug report! I think I will tag this as real bug since I do not see any major reason why this should not work.

@edwinb
Copy link
Contributor

edwinb commented Mar 5, 2017

It's because of the 'List' - the positivity check in Idris doesn't allow this because it only allows recursive arguments if they are either direct uses of the type, or the return type of a higher order function.

There's no reason not to allow this, it just needs implementing.

@edwinb
Copy link
Contributor

edwinb commented Mar 5, 2017

Oh, and the other issue is that 'calculate' is used as an argument to a higher order function, and the totality checker can't immediately see that this is valid. This is much harder to do anything about. I don't know how Coq manages to spot that this is okay... I suppose I'll have to read up on how their totality checker works these days.

@ahmadsalim ahmadsalim changed the title Totality checker issue on mutually inductive types Positivity checker issue when inductive data-type use is in a parameter of another data-type Mar 5, 2017
@ahmadsalim ahmadsalim removed this from the 1.0 milestone Mar 9, 2017
@ahmadsalim ahmadsalim changed the title Positivity checker issue when inductive data-type use is in a parameter of another data-type Totality checker issue when inductive data-type use is in a parameter of another data-type Oct 23, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants