Haskell Parsing: x ++ y : z - parsing

In Haskell, why is x ++ y : z parsed as x ++ (y : z) and not as (x ++ y) : z?
For instance, [1] ++ 2 : [3] evaluates to [1,2,3].
Both (++) and (:) are right-associative with precedence 5.

The fact that they are right associative means that these are parsed "right-to-left" so to speak. It thus means that x ⊕ y ⊕ z is parsed as x⊕ (y ⊕ z). So that means that x ++ y : z is indeed parsed as x ++ (y : z).
There are good reasons to make both (:) and (++) right associative. For the "cons" (:) operator, it means that we can write 1 : 4 : 2 : [], since it is parsed as 1 : (4 : (2: [])), which is correct in terms of the types. If would parse it like ((1:4):2:[]), then 1:4 would for example be wrong, since it expects an item as the first operand, and list of these items as the second operand. We can of course still let the Haskell parser parse it as a list, but that would result in a large amount of extra parenthesis.
For (++) it is better to parse it right-to-left as well due to performance reasons. x ++ y takes linear time in the size of x. So that means that if we parse x ++ (y ++ z), it will take |x| + |y| steps. If we would parse this as (x ++ y) ++ z, it would take 2×|x|+|y|, since the first time we apply (x ++ y) it runs in the size of x, but then (x ++ y) ++ z runs in the size of x ++ y. This thus would mean that if we concatenate n lists each with a size of m, it will not run in O(n×m), but in O(n2×m).

Related

How to recover intermediate computation results from a function using "with"?

I wrote a function on the natural numbers that uses the operator _<?_ with the with-abstraction.
open import Data.Maybe
open import Data.Nat
open import Data.Nat.Properties
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
fun : ℕ → ℕ → Maybe ℕ
fun x y with x <? y
... | yes _ = nothing
... | no _ = just y
I would like to prove that if the result of computing with fun is nothing then the original two values (x and y) fulfill x < y.
So far all my attempts fall short to prove the property:
prop : ∀ (x y)
→ fun x y ≡ nothing
→ x < y
prop x y with fun x y
... | just _ = λ()
... | nothing = λ{refl → ?} -- from-yes (x <? y)}
-- This fails because the pattern matching is incomplete,
-- but it shouldn't. There are no other cases
prop' : ∀ (x y)
→ fun x y ≡ nothing
→ x < y
prop' x y with fun x y | x <? y
... | nothing | yes x<y = λ{refl → x<y}
... | just _ | no _ = λ()
--... | _ | _ = ?
In general, I've found that working with the with-abstraction is painful. It is probably due to the fact that with and | hide some magic in the background. I would like to understand what with and | really do, but the "Technical details" currently escape my understanding. Do you know where to look for to understand how to interpret them?
Concrete solution
You need to case-split on the same element on which you case-split in your function:
prop : ∀ x y → fun x y ≡ nothing → x < y
prop x y _ with x <? y
... | yes p = p
In the older versions of Agda, you would have had to write the following:
prop-old : ∀ x y → fun x y ≡ nothing → x < y
prop-old x y _ with x <? y
prop-old _ _ refl | yes p = p
prop-old _ _ () | no _
But now you are able to completely omit a case when it leads to a direct contradiction, which is, in this case, that nothing and just smth can never be equal.
Detailed explanation
To understand how with works you first need to understand how definitional equality is used in Agda to reduce goals. Definitional equality binds a function call with its associated expression depending on the structure of its input. In Agda, this is easily seen by the use of the equal sign in the definition of the different cases of a function (although since Agda builds a tree of cases some definitional equalities might not hold in some cases, but let's forget this for now).
Let us consider the following definition of the addition over naturals:
_+_ : ℕ → ℕ → ℕ
zero + b = b
(suc a) + b = suc (a + b)
This definition provides two definitional equalities that bind zero + b with b and (suc a) + b with suc (a + b). The good thing with definitional equalities (as opposed to propositional equalities) is that Agda automatically uses them to reduce goals whenever possible. This means that, for instance, if in a further goal you have the element zero + p for any p then Agda will automatically reduce it to p.
To allow Agda to do such reduction, which is fundamental in most cases, Agda needs to know which of these two equalities can be exploited, which means a case-split on the first argument of this addition has to be made in any further proof about addition for a reduction to be possible. (Except for composite proofs based on other proofs which use such case-splits).
When using with you basically add additional definitional equalities depending on the structure of the additional element. This only makes sense, understanding that, that you need to case-split on said element when doing proofs about such a function, in order for Agda once again to be able to make use of these definitional equalities.
Let us take your example and apply this reasoning to it, first without the recent ability to omit impossible cases. You need to prove the following statement:
prop-old : ∀ x y → fun x y ≡ nothing → x < y
Introducing parameters in the context, you write the following line:
prop-old x y p = ?
Having written that line, you need to provide a proof of x < y with the elements in the context. x and y are just natural so you expect p to hold enough information for this result to be provable. But, in this case, p is just of type fun x y ≡ nothing which does not give you enough information. However, this type contains a call to function fun so there is hope ! Looking at the definition of fun, we can see that it yields two definitional equalities, which depend on the structure of x <? y. This means that adding this parameter to the proof by using with once more will allow Agda to make use of these equalities. This leads to the following code:
prop-old : ∀ x y → fun x y ≡ nothing → x < y
prop-old x y p with x <? y
prop-old _ _ p | yes q = ?
prop-old _ _ p | no q = ?
At that point, not only did Agda case-split on x <? y, but it also reduced the goal because it is able, in both cases, to use a specific definitional equality of fun. Let us take a closer look at both cases:
In the yes q case, p is now of type nothing ≡ nothing and q is of type x < y which is exactly what you want to prove, which means the goal is simply solved by:
prop-old _ _ p | yes q = q
I the no q case, something more interesting happens, which is somewhat harder to understand. After reduction, p is now of type just y ≡ nothing because Agda could use the second definitional equality of fun. Since _≡_ is a data type, it is possible to case-split on p which basically asks Agda: "Look at this data type and give me all the possible constructors for an element of type just y ≡ nothing". At first, Agda only finds one possible constructor, refl, but this constructor only builds an element of a type where both sides of the equality are the same, which is not the case here by definition because just and nothing are two distinct constructors from the same data type, Maybe. Agda then concludes that there are no possible constructors that could ever build an element of such type, hence this case is actually not possible, which leads to Agda replacing p with the empty pattern () and dismissing this case. This line is thus simply:
prop-old _ _ () | no _
In the more recent versions of Agda, as I explained earlier, some of these steps are done directly by Agda which allows us to directly omit impossible cases when the emptiness of a pattern can be deduced behind the curtain, which leads to the prettier:
prop : ∀ x y → fun x y ≡ nothing → x < y
prop x y _ with x <? y
... | yes p = p
But it is the same process, just done a bit more automatically. Hopefully, these elements will be of some use in your journey towards understanding Agda.

How to prove element addition is injective for a cubical finite multi set?

I'm playing around with the type of finite multisets as defined in the cubical standard library here:
https://github.com/agda/cubical/blob/0d272ccbf6f3b142d1b723cead28209444bc896f/Cubical/HITs/FiniteMultiset/Base.agda#L15
data FMSet (A : Type ℓ) : Type ℓ where
[] : FMSet A
_∷_ : (x : A) → (xs : FMSet A) → FMSet A
comm : ∀ x y xs → x ∷ y ∷ xs ≡ y ∷ x ∷ xs
trunc : isSet (FMSet A)
I was able to reproduce the proofs for count extensionality and one of my lemmas I showed that you can remove a element from both sides of an equality and keep the equality.
It was similar to this one: https://github.com/agda/cubical/blob/0d272ccbf6f3b142d1b723cead28209444bc896f/Cubical/HITs/FiniteMultiset/Properties.agda#L183
remove1-≡-lemma : ∀ {a} {x} xs → a ≡ x → xs ≡ remove1 a (x ∷ xs)
remove1-≡-lemma {a} {x} xs a≡x with discA a x
... | yes _ = refl
... | no a≢x = ⊥.rec (a≢x a≡x)
My proofs weren't using the same syntax but in the core libraries syntax it was
cons-path-lemma : ∀ {x} xs ys → (x ∷ xs) ≡ (x ∷ ys) → xs ≡ ys
where the proof is using remove1-≡-lemma path composed on both side of a path which is the argument path functionally composed with remove1 x.
This requires the type of the values to have decidable equality as remove1 doesn't make sense without it. But the lemma itself doesn't mention decidable equality, and so I thought I would try to prove it without having that as a hypothesis. Its now a week later and I'm at my wits end because this seems so 'obvious' but so stubborn to prove.
I'm thinking that my intuition about this being provable may be coming from my classical math background, and so it doesn't follow constructively/contiuously.
So my question is: Is this provable with no assumptions on the element type? If so what would the general structure of the proof look like, I have had trouble getting proofs that want to induct over the two FMSets simultaneously to work (as I'm mostly guessing when trying to get paths to line up as necessary). If it is not provable with no assumptions, is it possible to show that it is equivalent in some form to the necessary assumptions?
I can't offer a proof but an argument why it should be provable without assuming decidability. I think finite multisets can be represented as functions Fin n -> A and equality between multisets f and g is given by a permutation phi : Fin n ~ Fin n, (that is invertible functions on Fin n) such that f o phi = g. Now
(a :: f) 0 = a
(a :: f) (suc i) = f i
If phi : Fin (suc n) ~ Fin (suc n) proves that a :: f = a :: g you can construct a psi : Fin n ~ Fin n which proves that f = g. If phi 0 = 0 then psi n = phi (suc n) otherwise you have to obtain psi by assigning phi^-1 0 to phi 0. However this case analysis is on Fin n.
I think representing the permutation group by swapping adjacent elements is just an inconvenient representation for this problem.

How to tell whether parentheses are necessary or not?

I have written a parser in Haskell, which parses formulas in the form of string inputs and produces a Haskell data type defined by the BNF below.
formula ::= true
| false
| var
| formula & formula
| ∀ var . formula
| (formula)
var ::= letter { letter | digit }*
Now I would like to create an instance of Show so that I can nicely print the formulas defined by my types (I don't want to use deriving (Show)). My question is: How do I define my function so that it can tell when parentheses are necessary? I don't want too many, nor too little parentheses.
For example, given the formula ∀ X . (X & Y) & (∀ Y . Y) & false which, when parsed, produces the data structure
And (And (Forall "X" (And (Var "X") (Var "Y"))) (Forall "Y" (Var "Y"))) False
we have
Too little parentheses: ∀ X . X & Y & ∀ Y . Y & false
Too much parentheses: (∀ X . (((X) & (Y)))) & (∀ Y . (Y)) & (false)
Just right: ∀ X . (X & Y) & (∀ Y . Y) & false
Is there a way to gauge how many parenthesis are necessary so that the semantics is never ambiguous? I appreciate any feedback.
Untested pseudocode:
instance Show Formula where
showsPrec _p True = "True"
showsPrec _p False = "False"
showsPrec p (And f1 f2) = showParen (p > 5) $
showsPrec 5 f1 . (" & " ++) . showsPrec 5 f2
showsPrec p (Forall x f) = showParen (p > 8) $
("forall " ++ x ++) . showsPrec 8 f
...
(I should probably use showString instead of those ++ above. It should work anyway, I think.)
Above, the integer p represents the precedence of the context where we are showing the current formula. For example, if we are showing f inside f & ... then p will have the precedence level of &.
If we need to print a symbol in a context which has higher precedence, we need to add parentheses. E.g. if f is a | b we can't write a | b & ..., otherwise it is interpreted as a | (b & ...). We need to put parentheses around a | b. This is done by the showParen (p > ...).
When we recurse, we pass the precedence level of the symbol at hand to the subterms.
Above, I chose the precedence levels randomly. You need to adjust them to your tastes. You should also check that the levels you choose play along the standard libraries. E.g. printing Just someFormula should not generate things like Just a & b, but add parentheses.

How "with" keyword works in agda ?? and also the code below ??

I am not able to understand it clearly. I tried to learn "with" keyword but there also i have doubt. Please help !!!
I wanted to understand the working of "with" and working of this code.
something-even : ∀ n → Even n ⊎ Even (suc n)
something-even zero = inj₁ zero
something-even (suc n) with something-even n
... | inj₁ x = inj₂ (suc-suc x)
... | inj₂ y = inj₁ y
(this states that either n is even or its successor is even). In fact, thm0 can be implemented without using recursion!
thm0 : ∀ x → ∃ λ y → Even y × x less-than y
thm0 n with something-even n
... | inj₁ x = suc (suc n) , suc-suc x , suc ref
... | inj₂ y = suc n , y , ref
If you are familiar with Haskell, you will notice that in Agda there are no if-statements and no case.
with does pattern-matching of the expression result. For example, with something-even n evaluates something-even n, and then pattern-matches on the following lines with ... | inj₁ x and ... | inj₂ y. These match the expression, to see if its value is constructed using inj₁ or inj₂ constructor, so that the value wrapped by them can be used in the right-hand-side expressions: suc (suc n) , suc-suc x , suc ref uses x determined by inj₁ x, and suc n , y , ref uses y determined by inj₂ y
The actual constructor names come from the definition of ⊎ - see the type of something-even joins types Even n and Even (suc n). So x in inj₁ x corresponds to a value of type Even n for given n, and y in inj₂ y corresponds to a value of type Even (suc n) for the same n.

Types containing with/rewrite clauses in agda, or, how to use rewrite instead of subst?

First some boring imports:
import Relation.Binary.PropositionalEquality as PE
import Relation.Binary.HeterogeneousEquality as HE
import Algebra
import Data.Nat
import Data.Nat.Properties
open PE
open HE using (_≅_)
open CommutativeSemiring commutativeSemiring using (+-commutativeMonoid)
open CommutativeMonoid +-commutativeMonoid using () renaming (comm to +-comm)
Now suppose that I have a type indexed by, say, the naturals.
postulate Foo : ℕ -> Set
And that I want to prove some equalities about functions operating on this type Foo. Because agda is not very smart, these will be heterogeneous equalities. A simple example would be
foo : (m n : ℕ) -> Foo (m + n) -> Foo (n + m)
foo m n x rewrite +-comm n m = x
bar : (m n : ℕ) (x : Foo (m + n)) -> foo m n x ≅ x
bar m n x = {! ?0 !}
The goal in bar is
Goal: (foo m n x | n + m | .Data.Nat.Properties.+-comm n m) ≅ x
————————————————————————————————————————————————————————————
x : Foo (m + n)
n : ℕ
m : ℕ
What are these |s doing in the goal? And how do I even begin to construct a term of this type?
In this case, I can work around the problem by manually doing the substitution with subst, but that gets really ugly and tedious for larger types and equations.
foo' : (m n : ℕ) -> Foo (m + n) -> Foo (n + m)
foo' m n x = PE.subst Foo (+-comm m n) x
bar' : (m n : ℕ) (x : Foo (m + n)) -> foo' m n x ≅ x
bar' m n x = HE.≡-subst-removable Foo (+-comm m n) x
Those pipes indicate that reduction is suspended pending the result of the expressions in question, and it typically boils down to the fact that you had a with block whose result you need to know to proceed. This is because the rewrite construct just expands to a with of the expression in question along with any auxiliary values that might be needed to make it work, followed by a match on refl.
In this case, it just means that you need to introduce the +-comm n m in a with block and pattern match on refl (and you'll probably need to bring n + m into scope too, as it suggests, so the equality has something to talk about). The Agda evaluation model is fairly straightforward, and if you pattern match on something (except for the faux pattern matches on records), it won't reduce until you pattern match on that same thing. You might even be able to get away with rewriting by the same expression in your proof, since it just does what I outlined for you.
More precisely, if you define:
f : ...
f with a | b | c
... | someDataConstructor | boundButNonConstructorVariable | someRecordConstructor = ...
and then you refer to f as an expression, you will get the pipes you observed for expression a only, because it matches on someDataConstructor, so at the very least to get f to reduce you will need to introduce a and then match on someDataConstructor from it. On the other hand, b and c, although they were introduced in the same with block, do no halt evaluation, because b doesn't pattern match, and c's someRecordConstructor is known statically to be the only possible constructor because it's a record type with eta.

Resources