Quickly simplifying the expression 'ite ("a"="b") x y' - lean

When being left with an expression of the form ite ("a"="b") x y which involves a decidable equality between two distinct string literals, it appear that simp on its own does not allow me to reduce this expressions to y. This is in contrast to the case of ite ("a"="a") x y which is reduced to x with simp. So I find myself doing a case
analysis cases decidable.em ("a"="b") with H H and then handling one case using exfalso and dec_trivial and the other by using simp [H]. So I am able to move forward, but I was wondering if there was a more idiomatic and shorter way to achieve the same result.

Either rw [if_neg (show "a" ≠ "b", from dec_trivial)] or simp [if_neg (show "a" ≠ "b", from dec_trivial)] is the easiest way I know.

Related

Pattern-matching syntax not Constructor application syntax

Given a two-place data constructor, I can partially apply it to one argument then apply that to the second. Why can't I use the same syntax for pattern matching?
data Point = MkPoint Float Float
x = 1.0 :: Float; y = 2.0 :: Float
thisPoint = ((MkPoint x) y) -- partially apply the constructor
(MkPoint x1 y1) = thisPoint -- pattern match OK
((MkPoint x2) y2) = thisPoint -- 'partially apply' the pattern, but rejected: parse error at y2
((MkPoint x3 y3)) = thisPoint -- this accepted, with double-parens
Why do I want to do that? I want to grab the constructor and first arg as an as-pattern, so I can apply it to a different second arg. (Yes the work-round in this example is easy. Realistically I have a much more complex pattern, with several args of which I want to split out the last.):
(mkPx#(MkPoint x4) y4) = thisPoint -- also parse error
thatPoint = mkPx (y4 * 2)
I think there's no fundamental reason to prevent this kind of match.
Certainly it wouldn't do to allow you to write
f (MkPoint x1) = x1
and have that match a partially-applied constructor, i.e. a function. So, one reason to specify it as it was specified here is for simplicity: the RHS of an # has to be a pattern. Simple, easy to parse, easy to understand. (Remember, the very first origins of the language were to serve as a testbed for PL researchers to tinker. Simple and uniform is the word of the day for that purpose.) MkPoint x1 isn't a pattern, therefore mkPx#(MkPoint x1) isn't allowed.
I suspect that if you did the work needed to carefully specify what is and isn't allowed, wrote up a proposal, and volunteered to hack on the parser and desugarer as needed, the GHC folks would be amenable to adding a language extension. Seems like a lot of work for not much benefit, though.
Perhaps record update syntax will scratch your itch with much less effort.
data Point = MkPoint {x, y :: Float}
m#(MkPoint { x = x5 }) = m { x = x5 + 1 }
You also indicate that, aside from the motivation, you wonder what part of the Report says that the pattern you want can't happen. The relevant grammar productions from the Report are here:
pat → lpat
lpat → apat
| gcon apat1 … apatk (arity gcon = k, k ≥ 1)
apat → var [ # apat] (as pattern)
| gcon (arity gcon = 0)
| ( pat ) (parenthesized pattern)
(I have elided some productions that don't really change any of the following discussion.)
Notice that as-patterns must have an apat on their right-hand side. apats are 0-arity constructors (in which case it's not possible to partially apply it) or parenthesized lpats. The lpat production shown above indicates that for constructors of arity k, there must be exactly k apat fields. Since MkPoint has arity 2, MkPoint x is therefore not an lpat, and so (MkPoint x) is not an apat, and so m#(MkPoint x) is not an apat (and so not produced by pat → lpat → apat).
I can partially apply [a constructor] to one argument then apply that to the second.
thisPoint = ((MkPoint x) y) -- partially apply the constructor
There's another way to achieve that without parens, also I can permute the arguments
thisPoint = MkPoint x $ y
thisPoint = flip MkPoint y $ x
Do I expect I could pattern match on that? No, because flip, ($) are just arbitrary functions/operators.
I want to grab the constructor and first arg as an as-pattern, ...
What's special about the first arg? Or the all-but-last arg (since you indicate your real application is more complex)? Do you you expect you could grab the constructor + third and fourth args as an as-pattern?
Haskell's pattern matching wants to keep it simple. If you want a binding to the constructor applied to an arbitrary subset of arguments, use a lambda expression mentioning your previously-bound var(s):
mkPy = \ x5 -> MkPoint x5 y1 -- y1 bound as per your q

proving Predicate logic with Isabelle

I'm trying to prove the following lemma:
lemma myLemma6: "(∀x. A(x) ∧ B(x))= ((∀x. A(x)) ∧ (∀x. B(x)))"
I'm trying to start by eliminating the forall quantifiers, so here's what I tried:
lemma myLemma6: "(∀x. A(x) ∧ B(x))= ((∀x. A(x)) ∧ (∀x. B(x)))"
apply(rule iffI)
apply ( erule_tac x="x" in allE)
apply (rule allE)
(*goal now: get rid of conj on both sides and the quantifiers on right*)
apply (erule conjE) (*isn't conjE supposed to be used with elim/erule?*)
apply (rule allI)
apply (assumption)
apply ( rule conjI) (*at this point, the following starts to make no sense... *)
apply (rule conjE) (*should be erule?*)
apply ( rule conjI)
apply ( rule conjI)
...
At the end I just started to act depending on the outcome of the previous apply, but it seems wrong to me, probably because there's some mistake in the beginning... Could someone please explain to me my error and how to finish this proof correctly?
Thanks in advance
Eliminating the universal quantifier at this early stage is not a good idea because you don't even have any value that you could plug in at that point (the x that you give is not in scope at that point, which is why it is printed with that orange background in Isabelle/jEdit).
After you do iffI you have two goals:
goal (2 subgoals):
1. ∀x. A x ∧ B x ⟹ (∀x. A x) ∧ (∀x. B x)
2. (∀x. A x) ∧ (∀x. B x) ⟹ ∀x. A x ∧ B x
Let's focus on the first one for now. You should first apply the introduction rules on the right-hand side, namely conjI and allI. That leaves you with
goal (3 subgoals):
1. ⋀x. ∀x. A x ∧ B x ⟹ A x
2. ⋀x. ∀x. A x ∧ B x ⟹ B x
3. (∀x. A x) ∧ (∀x. B x) ⟹ ∀x. A x ∧ B x
Now you can apply allE instantiated with x and the first goal becomes ⋀x. A x ∧ B x ⟹ A x, which you can then solve with erule conjE and assumption. The second goal works similarly.
For the last goal, it is similar again: apply the introduction rules first, then apply the elimination rules and assumption and you're done.
Of course, all the standard provers for Isabelle such as auto, force, blast and even the simple ones like metis, meson, iprover can easily solve this automatically, but that's probably not what you were going for here.

Haskell - How do filter and head work in combination with where?

Here's the code.
largestDivisible :: (Integral a) => a
largestDivisible = head (filter p [100000,99999..])
where p x = x `mod` 3829 == 0
I am little bit confused. What is p in this case? Also, I do not understand the where expression in this particular example, because we got two expressions with p and x on the left side and we have one alignment, which is actually a boolean.
I would appreciate, if someone could explain me the above code.
p is a function, which accepts an argument x and returns True only if x is divisible by 3829. You can use where to define local functions just like you define local "values", using the same f x = y syntax you use to define top-level functions.

Which is a correct program for given statement?

Problem statement:
Find the right triangle that has integers for all sides and all sides equal to or smaller than 10 has a perimeter of 24.
Which solution of following two is correctly interpreting the problem and gives the right answer?
If the First Solution is not correct then how to avoid such programming error in similar scenario?
First Solution:
ghci> let rightTriangles = [(a, b, c) | a <- [1..10], b <- [1..10], c <- [1..10], a^2 + b^2 == c^2, a+b+c == 24]
ghci> rightTriangles
[(6,8,10),(8,6,10)]
Second Solution:
ghci> let rightTriangles' = [ (a,b,c) | c <- [1..10] , b <- [1..c] , a <- [1..b] , a^2 + b^2 == c^2, a+b+c == 24]
ghci> rightTriangles'
[(6,8,10)]
As it stands I think the problem is slightly under defined.
The first four words "Find the right triangle" (emphasis mine) suggests a unique answer, which is almost certainly meant to be (6,8,10). However the rest of the problem is met by all triangles that are congruent to (6,8,10), of which (8,6,10) is certainly one so it is not wrong per se, but probably not what you are meant to get.
Another way of looking at this is that the problem defines an equivalence class of which (6,8,10) is the canonical representation, however the problem does not explicitly ask for the canonical representation (though we can infer it is probably the expected answer and therefore should use your second solution)
You have to filter out different permutations. By restriction a <= b and b <= c, you can accomplish this. You did this in the second answer by restriction the input domain of b and c. b <- [1..c] implies b <= c.

Haskell: foldl' accumulator parameter

I've been asking a few questions about strictness, but I think I've missed the mark before. Hopefully this is more precise.
Lets say we have:
n = 1000000
f z = foldl' (\(x1, x2) y -> (x1 + y, y - x2)) z [1..n]
Without changing f, what should I set
z = ...
So that f z does not overflow the stack? (i.e. runs in constant space regardless of the size of n)
Its okay if the answer requires GHC extensions.
My first thought is to define:
g (a1, a2) = (!a1, !a2)
and then
z = g (0, 0)
But I don't think g is valid Haskell.
So your strict foldl' is only going to evaluate the result of your lambda at each step of the fold to Weak Head Normal Form, i.e. it is only strict in the outermost constructor. Thus the tuple will be evaluated, however those additions inside the tuple may build up as thunks. This in-depth answer actually seems to address your exact situation here.
W/R/T your g: You are thinking of BangPatterns extension, which would look like
g (!a1, !a2) = (a1, a2)
and which evaluates a1 and a2 to WHNF before returning them in the tuple.
What you want to be concerned about is not your initial accumulator, but rather your lambda expression. This would be a nice solution:
f z = foldl' (\(!x1, !x2) y -> (x1 + y, y - x2)) z [1..n]
EDIT: After noticing your other questions I see I didn't read this one very carefully. Your goal is to have "strict data" so to speak. Your other option, then, is to make a new tuple type that has strictness tags on its fields:
data Tuple a b = Tuple !a !b
Then when you pattern match on Tuple a b, a and b will be evaluated.
You'll need to change your function regardless.
There is nothing you can do without changing f. If f were overloaded in the type of the pair you could use strict pairs, but as it stands you're locked in to what f does. There's some small hope that the compiler (strictness analysis and transformations) can avoid the stack growth, but nothing you can count on.

Resources