How does the order of implicit arguments affect idris?
I just read this post and I got curious about MkPair's type signature.
I tried MkPair 10 on REPL and I got
(input):Can't infer argument B to Builtins.MkPair
And this is exactly what I expected. From its type signature Builtins.MkPair : {A : Type} -> {B : Type} -> (a : A) -> (b : B) -> (A, B), I have to pass B(whether it's implicit or explicit) before apply a value for a.
At the same time, I expected q 10 to work, cause its type is q : {A : Type} -> (a : A) -> {B : Type} -> (b : B) -> (A, B) which tells me that I don't need any value for B before I apply a value for A and a.
But it also failed with the same message!
(input):Can't infer argument B to Main.q
What happens to q?
And I have one more question . Before I found that q worked neither, I was gonna ask the reason that Idris compiler prefers MkPair's signature to q's one. MkPair looks unnecessarily eager to me. Why does it demand B too early?
Without any context to guide the compiler, I guess Idris stays true to its eager by default attitude and tries to infer all the implicit arguments that appear before the last "explicit" one specified, before doing automatic partial application.
Note that you can suppress this behavior by placing the expression in an appropriately typed hole:
the ({b : Type} -> b -> (Nat, b)) (q 10)
-- or
r : {b : Type} -> b -> (Nat, b)
r = q 10
Related
I have encountered a problem with some code I am trying to write in Idris 2. I would like to resolve this issue, but more importantly, I wish to understand it more deeply and develop some skills in diagnosing such issues in general.
I have distilled the problem to the following relatively trivial example:
data D : Nat -> Type where
V : (n : Nat) -> D n
d : (n : Nat) -> D n
d n = V n
f : D n -> String
f (V n) = show n
t : Nat -> String
t = f . d
The definition of t fails type checking with the following output:
Error: While processing right hand side of t. Can't solve constraint between: ?n [no locals in scope] and n.
Test:11:9--11:10
07 | f : D n -> String
08 | f (V n) = show n
09 |
10 | t : Nat -> String
11 | t = f . d
Some experimentation has revealed that the following alternative definitions for t also fail type checking:
t : Nat -> String
t n = (f . d) n
t : Nat -> String
t = \n => (f . d) n
While these alternatives type check successfully:
t : Nat -> String
t n = f (d n)
t : Nat -> String
t = \n => f (d n)
I am endeavouring to learn Idris (for the second time), and so while I could move on with the definitions which don't involve function composition, I would like to improve my understanding.
It seems to me that the definitions which pass type checking are simply syntactic alternatives with identical semantics and behaviour, and I don't understand why the function composition definitions fail type checking. I would also like to understand the particular error message the type checker reports, so that I can deepen my understanding and resolve similar type checking errors in the future.
I have a few broad questions:
How should I interpret the error reported by the type checker in this example, and how can I gather more information about the ?n and n types mentioned? I particularly welcome any advice or tips on how to go about understanding and resolving such an error (teach a man to fish, as the saying goes).
Why do the definitions involving function composition fail type checking?
What is the best solution for this example? Should I just use a definition which does not involve function composition? Is there a better alternative?
Let look at the types involved
Prelude.. : (b -> c ) -> (a -> b ) -> a -> c
f : D n -> String
d : (n : Nat) -> D n
The problem is:
(a -> b )
(n : Nat) -> D n
cannot be unified because (a -> b) does not allow the value of the argument to determine the type of return value.
I'm a beginner with Idris. In Idris2 version 0.3.0, I observed a strange behavior.
Why doesn't this code type check ?
f : Type -> Type -> Type
f a b = (c : Bool) -> if c then a else b
While processing right hand side of f. Main.case block in f is not accessible in this context.
While this code type checks without issues:
f1 : Type -> Type -> Bool -> Type
f1 a b c = if c then a else b
f' : Type -> Type -> Type
f' a b = (c : Bool) -> f1 a b c
Is this a bug?
Initially, I was trying to prove a stupid theorem which should be obvious, but Refl doesn't work. It looks like it's unable to understand that the variables match.
module Main
import Data.Nat
t : Nat -> Nat -> Nat
t l r = if lte l r then l else r
prop : Nat -> Nat -> Type
prop a b = (t a b = if lte a b then a else b)
proof_prop : prop a b
proof_prop = ?imlost
Your if_then_else_ using program starts failing in commit 04a0f5001f:
Correct multiplicities when checking Pi binders
We've always just used 0, which isn't correct if the function is going
to be used in a runtime pattern match. Now calculate correctly so that
we're explicit about which type level variables are used at runtime.
This might cause some programs to fail to compile, if they use
functions that calculate Pi types. The solution is to make those
functions explicitly 0 multiplicity. If that doesn't work, you may
have been accidentally trying to use compile-time only data at run
time!
Fixes #1163
The solution is to mark your f function as type-level-only:
0 f : Type -> Type -> Type
f a b = (c : Bool) -> if c then a else b
In the agda docs, I read that when "some meta-variable other than the goals cannot be solved the code will be highlighted in yellow"
I'm trying to understand this in a somewhat degenerate case.
If I define a regular product type then a stupid program works fine.
data _==_ {l}{X : Set l}(x : X) : X -> Set where
refl : x == x
data prod (A B : Set) : Set where
_,,_ : A → B → prod A B
fst' : {A B : Set} → prod A B → A
fst' (x ,, x₁) = x
stupid : fst' (3 ,, 3) == 3
stupid = refl
However, if I use a product as a special case of a dependent product, I get the yellow highlighting for stupid''''. Specifically, the fst and and the second 3 are highlighed yellow. Why do all the other stupid*'s work except for stupid''''? Are there any general tips for debugging yellow highlighting errors in agda?
record Sg {l}(S : Set l)(T : S -> Set l) : Set l where
constructor _,_
field
fst : S
snd : T fst
open Sg public
_*_ : forall {l} -> Set l -> Set l -> Set l
S * T = Sg S \ _ -> T
infixr 40 _,_
infixr 20 _*_
threethree : Nat * Nat
threethree = 3 , 3
three : Nat
three = fst threethree
stupid'' : three == 3
stupid'' = refl
stupid''' : fst (threethree) == 3
stupid''' = refl
--here's the yellow highlighting
stupid'''' : fst (3 , 3) == 3
stupid'''' = refl
--here's the yellow highlighting
stupid'''' : fst (3 , 3) == 3
stupid'''' = refl
This is because Agda can't infer the type of (3 , 3) to supply it to fst.
"But that's just Nat * Nat!"
Not necessarily, it can be
Sg Nat \n -> if n == 3 then Nat else Bool
or any other weird type that gives Nat as a type of the second element whenever the first element is 3 and does something completely different in all other cases.
And Agda's unification machinery always either finds a unique solution or gives up.
You've asked Agda to solve the following unification problem:
_T 3 =?= Nat
and clearly there are way too many different _Ts that return Nat when the argument is 3.
Why do all the other stupid*'s work except for stupid''''
Because in all the other ones there's no ambiguity:
in stupid the type of the second element does not depend on the first element (due to the definition of prod)
in other cases you explicitly specify the type of the argument (via a standalone declaration)
This question is a request for references or explanation.
The main idea is: What if I add every axiom from standard library of Coq?
Will it raise a contradiction or they are well-adjusted to each other?
What are other reliable sources of information about Coq other than a standard library of Coq. (I saw a bunch papers from nineties, eighties. Obviously there are plenty of variants of type theories. Which one is for contemporary Coq? Or should I think "Everything that is known may be found in https://coq.inria.fr/refman/ , in https://sympa.inria.fr/sympa/arc/coq-club/1993-12/ and in standard library.")
(A) Do you know paper or other source where it is proved that some axioms may be properly added to Coq?
Properly here means that the extended system will be a conservative extension of previous OR will be considered to be safe strengthening.
(B) Personally, I am interested in these axioms:
0) ex2sig (is it consistent?)
Axiom ex2sig : forall (A:Type) (P:A->Prop), #ex A P -> #sig A P.
1) LEM
2) Functional extensionality
Axiom functional_extensionality_dep : forall {A} {B : A -> Type},
forall (f g : forall x : A, B x),
(forall x, f x = g x) -> f = g.
3) Choice
Theorem choice :
forall (A B : Type) (R : A->B->Prop),
(forall x : A, exists y : B, R x y) ->
exists f : A->B, (forall x : A, R x (f x)).
4) "Terms-as-Types"
Definition E := Type.
Axiom R : forall x : E, x -> E.
Axiom R_inj : forall (x : E) (a b : x), R x a = R x b -> a = b.
5) Proof-Irrelevance
Axiom proof_irrelevance : forall (P:Prop) (p1 p2:P), p1 = p2.
6) ... (you may recommend your axiom in comments)
e.g. Markov's principle
Parameter P:nat -> Prop.
Theorem M:((forall n,(P n \/ ~ (P n)))/\ ~(forall n, ~(P n)) -> exists n,P n).
But we are not very much interested in Markov's principle.
Because we need some very strong classic theory with LEM(so the Markov principle is proved), with some strongest form of Choice(which will imply LEM), extensionality, etc. (Which axioms can we also add?) (By the way, there are many variants of choice in Coq: relational)
p.s. Shall extensive use of "noncomputational" axioms in Coq be treated as misuse of it? (I think no, but I am not sure.)
Which properties of Coq will I loose after adding the axioms? (you may say both reference and/or opinion)
p.p.s. The question is big and consist of many connected pieces, so every partial answer is welcome.
So I've noticed that in Idris if you define your own list or vector like type — for example the following type I've found to be useful:
data HFVec : (f : Type -> Type) -> (n : Nat) -> Vec n Type -> Type where
Nil : HFVec f Z []
(::) : (a : f t) -> HFVec f n ts -> HFVec f (S n) (t :: ts)
— then you get list syntax for free:
test : HFVec List 2 [Int, String]
test = [[3], [""]]
I assume this is done when you have a constructor named ::, but I don't know for certain. In the same way you get do-notation if you have a constructor named >>= even if there is no monad implementation:
data Test : Type -> Type where
Pure : a -> Test a
(>>=) : Test a -> (a -> Test b) -> Test b
test : Test Int
test = do
Pure 1
x <- Pure 2
Pure x
This is a pretty cool feature, the only thing is I have not found it documented anywhere. It would be good to know exactly how these mechanisms work so one can know under exactly what circumstances they can be expected to work. Also, are these kind of rules the privilege of the compiler, or can the user make them with the syntax and dsl features?