Open Sintrastes opened 5 years ago
@Sintrastes I had a quick play with your code a managed to get a working solution, the code is at the end. Essentially, I made the auto implicit an explicit argument, and remove a possible implicit misidentification by the compiler (capitalised compatible).
Thus the follow 'works'.
λΠ> (A <> B $ Refl) <> A $ Refl
The following is wrong, but I shall leave it here for posterity: I think what is happening here is that Idris is having trouble finding the proof as your operator is Right Associative. When nesting you are asking it to find something it doesn't have the information for. In this case, I believe this will be 'expected behaviour'.
I believe, the reason that Idris is not finding the proof is that it doesn't have the information required. I get incomplete term when performing nested operations. I am not sure this is correct, but I am not too sure. I'll look at this in detail later, if I have time.
Again wrong. We can rewrite your code to ensure Idris does find the nested proof by making the operator left associative. I have a local working version that does work. But I made more changes.
I have a different version of the code, locally, that follows some good design patterns when working with Idris code and proving things.
I am not going to provide my entire local version, as it might be a good exercise to complete for you to get your teeth into. My interface is at the very end.
I hope this helps.
infixr 9 <>
interface PartialMonoid (m : Type) where
Compatible : m -> m -> Bool
(<>) : (a : m) -> (b : m) -> (Compatible a b = True) -> m
data MyPos : Type where
A : MyPos
B : MyPos
C : MyPos
op : (a : MyPos) -> (b : MyPos) -> Bool
op A A = True
op B B = True
op C C = True
op A B = True
op B A = True
op A C = True
op C A = True
op x y = False
PartialMonoid MyPos where
Compatible = op
(<>) A A (Refl) = A
(<>) B B (Refl) = B
(<>) C C (Refl) = C
(<>) A B (Refl) = B
(<>) A C (Refl) = C
(<>) C A (Refl) = C
(<>) B A (Refl) = B
(<>) B C (Refl) impossible
(<>) C B (Refl) impossible
Hint Hint
infixl 9 <>
interface PartialMonoid (m : Type) where
data Compatible : m -> m -> Type
merge : (a : m) -> (b : m) -> (Compatible a b) -> m
@jfdm Thank you for your suggestions and taking a look at this issue. Unfortunately, I still run into the same issue when following your suggestions (maybe there is still something I'm doing differently?)
interface PartialMonoid (m : Type) where
data Compatible : m -> m -> Type
merge : (a : m) -> (b : m) -> (Compatible a b) -> m
data MyPos : Type where
A : MyPos
B : MyPos
C : MyPos
data MyPosCompat : MyPos -> MyPos -> Type where
MyRefl : (a : MyPos) -> MyPosCompat a a
CompatAB : MyPosCompat A B
CompatBA : MyPosCompat B A
CompatAC : MyPosCompat A C
CompatCA : MyPosCompat C A
myMerge : (a : MyPos) -> (b : MyPos) -> (p : MyPosCompat a b) -> MyPos
myMerge A A (MyRefl A) = A
myMerge B B (MyRefl B) = B
myMerge C C (MyRefl C) = C
myMerge A B CompatAB = B
myMerge B A CompatBA = B
myMerge A C CompatAC = C
myMerge C A CompatCA = C
myMerge B C (MyRefl x) impossible
myMerge C B (MyRefl x) impossible
PartialMonoid MyPos where
Compatible = MyPosCompat
merge = myMerge
-- The following operator works as intended
infixl 9 <.>
(<.>) : (a : MyPos) -> (b : MyPos) -> {auto p : MyPosCompat a b} -> MyPos
(<.>) a b {p=p} = myMerge a b p
-- The following operator still does not work
infixl 9 <>
(<>) : PartialMonoid m => (a : m) -> (b : m) -> {auto p : Compatible a b} -> m
(<>) a b {p=p} = merge a b p
I am still bewildered as to why writing an operator specifically for MyPos
works as intended, but the generic <>
operator gives me incomplete term
errors. This seems to me like an issue with the interface/instance mechanism in Idris, and how it interacts with implicits.
Note: This was originally a question on stack exchange, but I got no response there, and this seems like it has a good chance of being a bug with Idris itself, so I figured I would post it as an issue here.
I'm writing an interface for partial monoids as follows:
With a simple implementation as proof of concept:
Whenever I try to evaluate something like
A <> B
in the REPL, I get the expected behavior. However, when evaluating (for instance)(A <> B) <> A
, instead of the expectedB
, I getThis is confusing to me, because if in the REPL I do:
then I get the expected
B
.I should also note that this seems to be an issue with how Idris' interface/implementation mechanism handles implicits. I get the expected behavior If I'm using some other operator (say
<..>
) defined normally (i.e. not as the instance of an interface).