{# Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. #} {#- Adapted from: https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/templates/appbuilder/flash.html -#} {# Split messages into two arrays: one for regular alerts, another for DAG import errors #} {% with messages = get_flashed_messages(with_categories=true) %} {% set dag_import_errors = [] %} {% set regular_alerts = [] %} {% if messages %} {% for category, m in messages %} {% if category == 'dag_import_error' %} {{ dag_import_errors.append((category, m)) if dag_import_errors.append((category, m)) != None else '' }} {% elif not (request.path == auth_manager.get_url_login() and 'access is denied' in m.lower()) %} {# Don't show 'Access is Denied' alert if user is logged out and on the login page. #} {{ show_message(m, category) }} {% endif %} {% endfor %} {% endif %} {% if dag_import_errors %}


|
|
| It's easy to make friends in Toontown. All you need to do is walk up to a Toon and click on them. |
When their detail panel appears, click on the blue Friends button.
A message will pop up asking if you'd like to make friends with that Toon.
|
| When you click "Yes" that Toon gets a message asking if they'd like to be
friends with you. If they say "Yes" too, they'll appear on your friends list. |
|
|
All of your Toontown friends appear on your Friends list. Friends who are online are in the Online Friends
panel, and everyone you are friends with is in the All Friends panel. Friends from your All Friends panel
will show up in the Online Friends panel as soon as they log in to Toontown.
|


{% extends 'fyh_emails/base.html' %} {% block content %}
Welcome to Hub@Penn! Hub@Penn is the central source of information about student resources at Penn. We hope students will use Hub@Penn to find services and communities that matter to them.
You've been invited to join the {{ name }} page! You are an Owner of the {{ name }} page, which means you have administrative access to edit the page. This lets you update the information that will be displayed here. You can also invite others to join as Owners and/or Editors.
Click the button below to join. You will need to sign in with your PennKey in order to complete the process. We hope you'll help us keep the platform updated for students to explore all the resources at Penn!
Join {{ name }}If you have any questions, feel free to respond to this email.
{% endblock %}


{%- set submitValue = (form.submitButtonText ? form.submitButtonText : "Submit") -%} {%- set submitAction = (form.submitAction ? form.submitAction : "sproutForms/entries/saveEntry") -%} {% if form.submitAction %} {# Submit form to third party #}
Thank you - your message has been submitted and you should receive a response in 4-5 working days


Kerry co-op to raise €90m from sale of Kerry Group shares
Co-op is selling shares for €112.50 apiece
Kerry co-op Society’s sale of 800,000 shares in listed food company Kerry Group was priced at €112.5 apiece, a 2.5 per cent discount to the stock’s close on Tuesday, Bloomberg reported.
The co-op will raise about €90 million from the share sale. The shares being sold represent 0.45 per cent of the company’s share capital.
A Bloomberg report noted that the seller will be subject to a 180-day lockup. Davy is the sole bookrunner for the shares. – Bloomberg


17. Recap of Achieving Consensus Protocols
Recap of Achieving Consensus
In the past couple concepts, you explored the challenges of achieving consensus in a distributed network and how different Blockchains use different Consensus protocols to solve this.
Let’s do a quick recap!
Byzantine Generals’ Problem
As we saw in the Byzantines’ General Problem, this challenge has been around for a while - achieving consensus in a distributed system with suboptimal communication between participants who do not necessarily trust each other isn’t new.
Proof of Work (PoW)
Bitcoin figured out how to use the Proof of Work algorithm to solve this issue.
The main innovation that Satoshi Nakamoto introduced in Bitcoin’s white paper is using proof of work (POW) to achieve consensus without a central authority and solve the double-spend problem.
How Does It Work?
PoW involves miner nodes, or miners, to solve a math puzzle that requires a lot of computation power. Whichever miner is able to solve the puzzle the fastest is able to add a block of transactions to the blockchain, and in return, they are paid the transaction fees from all the transactions included in the block as well as paid by the network with bitcoins that were newly created upon the “mining” of the block.
Potential Issues
2 Commonly discussed issues with Proof of Work are:
- Extremely High-Energy Consumption
- A Monopoloy of Miners which Leads to a Concern for System Centralizations
In addition to Proof of Work, we looked at other forms of Consensus
Proof of Stake
In the Proof-of-Stake Consensus Protocol, there are no more miners; instead, there are Validators. These validators, or stakeholders, determine which block makes it onto the blockchain. In order to validate transactions and create blocks, validators put up their own coins as “stake”. Think of it as placing a bet - if they validate a fraudulent transaction, they lose their holdings as well as their rights to participate as a validator in the future. In theory, this check incentivizes the system to validate only truthful transactions.
Potential Issues
We discussed the “Nothing At Stake” problem in which a bad acting Validator places bets on multiple forks so they theoretically always win out in the end.
Proposed Solutions
Slasher Strategy which entails penalizing validators if they simultaneously create blocks on multiple chains.
Additionally there’s the Punisher Strategy which simply punishes validators for creating blocks on the wrong chain. In this method, Validators will be motivated to be selective and conscious about the blockchain in which they put their stake.
Delegated Byzantine Fault Tolerance (dBFT)
dBFT uses a system similar to a democracy where Ordinary Nodes the system vote on representative Delegate Nodes to decide which blocks should be added to the blockchain. When it’s time to add a block, a Speaker is randomly assigned from the group of Delegates to create a new block and propose the new block. 66.66% of delegates need to approve on the block for it to pass.
Potential Issues
Two issues we explored were the case of the Dishonest Speaker and the Dishonest Delegate.
Dishonest Speaker
There is always a chance the Speaker, who is randomly selected from the Delegates, could be dishonest or malfunction. In this situation, the network needs to rely on honest delegates to vote the proposed block down so it doesn’t reach 66% approval. It is up to users of protocol who vote on Delegates, to find out which delegates are not trustworthy and vote on other delegates that are truthful.
Dishonest Delegate
In this case, the chosen Speaker is honest but there are Dishonest Delegates in the system meaning even if they receive a proposal for new block that is faulty, they can say it is valid. If it is a minority of delegates that are dishonest, the block will not make it and new speaker is elected.
Who’s Using It?
NEO is a big advocator of this protocol.
In Conclusion
While, Proof of Work and Proof of Stake are definitely the more popular choices, there are newer mechanisms coming up and proving themselves.
Remember that a consensus algorithm gets its reputation from being safe for a long period of time.
There is no “perfect” consensus mechanism, and chances are that there never will be, but it is interesting to see newer cryptocurrencies coming out with their own protocols and important to understand their pros and cons.


|
My Project
|
Public Member Functions | |
| def | __init__ (self, loc, condition) |
| def | getloc (self) |
| def | addcondition (self, loc, condition) |
| def | append (self, statement) |
| def | execute (self, makefile, context) |
| def | dump (self, fd, indent) |
| def | to_source (self) |
| def | __eq__ (self, other) |
| def | __iter__ (self) |
| def | __len__ (self) |
| def | __getitem__ (self, i) |
| Public Member Functions inherited from pymake.parserdata.Statement | |
| def | execute (self, makefile, context) |
| def | to_source (self) |
| def | __eq__ (self, other) |
| def | __ne__ (self, other) |
Static Public Member Functions | |
| def | condition_source (statement, index) |
Public Attributes | |
| loc | |
A set of related Conditions. This is essentially a list of 2-tuples of (Condition, list(Statement)). The parser creates a ConditionBlock for all statements related to the same conditional group. If iterating over the parser's output, where you think you would see an ifeq, you will see a ConditionBlock containing an IfEq. In other words, the parser collapses separate statements into this container class. ConditionBlock instances may exist within other ConditionBlock if the conditional logic is multiple levels deep.
Definition at line 615 of file parserdata.py.
|
static |
Convert a condition to its source representation. The index argument defines the index of this condition inside a ConditionBlock. If it is greater than 0, an "else" will be prepended to the result, if necessary.
Definition at line 706 of file parserdata.py.


Fill in all steps for completing resubmit process.
{{item.label}}
Please upload all files in pdf format,upload only A4 Size, portrait orientation and file size should be less than 4 MB.
For registration of individuals as Auditors : Rs 6,000.00
Follow the guidelines to payment process.
If yes, you will not be able to revert back.


Percentage of composition of essential oils from Rhaponticum carthamoides roots of soil-grown plants (SGR) and hairy roots (HR).
The concentrations of the main compounds were signified in bold.
RI: relative retention index on Rtx-1 column, RI lit: relative retention index of literature.
t: traces (percentage value less than 0.05%).


Learning Styles
Thursday, August 21, 2014
After taking this personal thinking style quiz, I learned that my Gregorc Thinking Style is:
- 28% Concrete Sequential
- 40% Abstract Sequential
- 36% Concrete Random
- 16% Abstract Random
That's a pretty wide spread. Does that mean I'm well rounded?
I didn't know what to make of that until I read the following summary of each thinking style. Below, I highlighted in green the traits that resonated with me and in red the ones that didn't. I think the fraction of green in each box is consistent with the scores I received in each "style":
I notice that I agree I'm reticent to work with people who have differing views (but I do like to compete with them!) and that I enjoy getting alone-time when I can experiment and commit concepts to memory. What I think this means for me at DevBootcamp is that I should enjoy the stimulating (and competitive?) environment working with peers, but also make sure to budget time to work alone so that I get to experiment and understand concepts fully.
Two of the biggest struggles so far in Phase 0 for me have been (1) remaining organized (keeping detailed records) with the myriad tasks we're asked to do each week and (2) working with peers in pairing sessions -- not being able to simply work alone. Understanding my learning style better, I think I understand the incubus of my problems: (1) as a Concrete Random thinker I eschew keeping detailed records and (2) as a Abstract Sequential thinker I really savor being able to work alone and it's difficult to diplomatically convince others of solutions in pairing sessions.
Here's my plan of action: (1) I'm going to be proactive in organizing my work & budgeting time. I'll try to start projects as early as possible so that I don't feel overwhelmed or stressed out as 'deadlines' approach. (2) I'm going to force myself to volunteer for pairing sessions without reservation so that I can increase my EQ (emotional quotient) to the extent that pairing won't be as annoying to me. I know I'd definitely like to increase my diplomatic / empathetic abilities!
Now, I'll consider the idea of growth vs fixed mindset (see more). Sadly, I know that up until now I've displayed some of the qualities of a person with a fixed mindset: I've felt criticism is something I'd like to avoid (I sought only praise). I also sometimes got depressed to think about the comparitive success of others instead of feeling envigorated and curious to learn from their success.
I want to adopt more of a growth mindset, and I plan to do so by first acknowledging these shortcomings, establishing my intent to change them, and making incremental behavioral adjustments to achieve that change. With regards to accepting criticism -- my incremental adjustment is to solicit feedback more frequently (with DBC feedback and in person at the end of pairing sessions, etc). This will give me more opportunites to try reducing feelings of defensiveness and concentrating on integrating this constructive feedback into my approaches. My incremental approach to appreciate success of other is to recognize that life isn't a competition between me and that successful person: it's a process where we try to get the most out of ourselves and that we should appreciate lessons from others who have excelled in that. I think taking a deep breath and framing the idea in this light will help me focus on the bigger picture and be a growth-minded individual.


By Phil Curtolo
The Substitute + The Naked Gun + Dangerous Minds = the hilarious new satire, High School High. Lovitz (A League of Their Own) is hysterical in his portrayal of a high school teacher trying to make a difference in the lives of his students.
He feels that the only way to get through to his students is by reaching their role model, a newly reformed, ex-gang member named Griff. Of course, spoofing directly off of Dangerous Minds, his stu-dents change their ways and the gangsta' look of Marion Berry High into something more like West Beverly High (think Clueless?)
However, when the senior's take their SAT's, and all mysteriously fail, it is up to Lovitz & Carrera (True Lies) to search for the culprit, who turns out to be the school's principal, Fletcher (Flower's in the Attic) and her gang of lowlife "homey-g's", who are also running a drug smug-gling ring (hence The Substitute, which can also be seen in the hysterical library scene).
So where does The Naked Gun fit into all of this. Throughout the film, shots of idiocy can be seen in the background, with some serious conver-sation in the foreground. For example, a few Afri-can-American students can be seen stumbling down a flight of concrete stairs, trying to walk up and hold up their baggy pants at the same time. Although the film is full of hysterics and ludicrous comedy, it lacks in the plot department.
What made this great comedy even more enjoyable, were the plush, reclining seats at the new Magic Theater in the Northampton Crossings. Even though, a small soda still costs a small fortune, you will never have to worry about kicking them over again, since you can rest them in the cup holders on the chairs, not taking any elbow-room away. Sur-prisingly, the new Magic Theaters costs only $5.75, which is a good price for what you get.
So if you want to see a good comedy and sit in good seats, then pick a good Saturday night, find a couple of good friends, eat a good dinner, and go to the Magic Cinema and see High School High. Grade: B, *** out of *****
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


2 writes to ScriptScope
System.Management.Automation (2)
engine\SessionState.cs (1)
81
GlobalScope.
ScriptScope
= GlobalScope;
engine\SessionStateScopeAPIs.cs (1)
239
newScope.
ScriptScope
= newScope;
5 references to ScriptScope
System.Management.Automation (5)
engine\ExecutionContext.cs (1)
429
scope.
ScriptScope
== scope && scope.Parent.Parent == null)) // it's the module's script scope (scope.Parent is global scope and scope.ScriptScope points to itself)
engine\SessionStateScope.cs (1)
34
_scriptScope = parentScope.
ScriptScope
;
engine\SessionStateScopeAPIs.cs (2)
82
result = _currentScope.
ScriptScope
;
214
internal SessionStateScope ScriptScope { get { return _currentScope.
ScriptScope
; } }
engine\SessionStateVariableAPIs.cs (1)
1157
scope = _currentScope.
ScriptScope
;


The Gamer Den
Mission Statement
Games in Stock
Investment Team
The Gamer Den
We invite all gamers to rise up!
Games currently in Stock
Buy, Sell, Rent your games here!!!
Ghost of Tsushima(PC/PS4/PS5)
Spider-Man(PS4/PS5)
Witcher 3(PC/PS4/PS5)
Our Team
Lisa Harlow
CEO - Founder and Developer
John Gilfoyle
Full Stack Developer - Research and Developer
Dani Daniels
Marketing - HR and Marketing


Hide irrelevant data and show your users only the data they need.
Hide all that information that does not add value to the experience of your users and streamlines their work.
Hidden Fields for Jira
Show the data only to those users (or groups of users) who need it, and hide the information for others.
To discover all the functionalities in detail visit the documentation page.
Show your data only to users who really need it
With Hidden Fields for Jira you will be able to hide fields and select a group of users with permissions so that they can view them.
Start improving your Jira users' experience!
Important: Hidden fields for Jira should be used for user experience purposes only. They should not be used for safety reasons.
Our apps are the result of innovation and continuous improvement
with the guarantee of being certified as a Silver Marketplace Partner.
Integrate SonarQube or SonarCloud with Jira. All the information on the quality of the code at your fingertips.
A new custom field type to be able to create lookup fields and link issues.
Tools for Jira administrators. Streamline work and reduce time for common tasks.


Employees Database
ID
Name
Email
CPF
RG
Add New Employee
{{ employee.id}}
{{ employee.nome}}
{{ employee.email}}
{{ employee.cpf}}
{{ employee.rg}}
Edit
Delete
�
{{form_title}}
Name
Name field is required
Email
Valid Email field is required
CPF
Contact number field is required
RG
Position field is required
morador
Position field is required


--- layout: post title: Avoiding Caching with Rails ActiveRecord date: 2014-08-14 15:08:10.000000000 -05:00 categories: - Rails tags: - activerecord - postgres - rails status: publish type: post published: true meta: _edit_last: '25054220' geo_public: '0' _publicize_pending: '1' publicize_facebook_url: https://facebook.com/10204620949391612 _wpas_done_5885047: '1' _publicize_done_external: a:1:{s:8:"facebook";a:1:{i:1471181839;b:1;}} publicize_twitter_user: adamnengland publicize_twitter_url: http://t.co/E4l3epu14t _wpas_done_881586: '1' publicize_linkedin_url: http://www.linkedin.com/updates?discuss=&scope=22010808&stype=M&topic=5905776717640777728&type=U&a=F3oR _wpas_done_881584: '1' publicize_tumblr_url: http://adamnengland.tumblr.com.tumblr.com/post/94751146090 _wpas_done_4227152: '1' author: login: adamnengland email<EMAIL_ADDRESS>display_name: adamnengland first_name: '' last_name: '' excerpt: !ruby/object:Hpricot::Doc
Today, I came across a puzzling issue with Rails 4.1, ActiveRecord, and Postgres when trying to select random records from a database table.
To demonstrate, let's use a simple social network API example. Clients will POST a list of user, and I'll "match" them to someone in my database.
Easy enough, for testing purposes we can just select a random user from our "users" table in postgres to simulate a match.
---Today, I came across a puzzling issue with Rails 4.1, ActiveRecord, and Postgres when trying to select random records from a database table.
To demonstrate, let's use a simple social network API example. Clients will POST a list of user, and I'll "match" them to someone in my database.
Easy enough, for testing purposes we can just select a random user from our "users" table in postgres to simulate a match.
{% highlight ruby %}
contacts = [{:id => 1}, {:id => 2}, {:id => 3}, {:id => 4}]
contacts.each do |c|
user = User.order('random()').first
c[:detail] = {:username => user.username}
end
{% endhighlight %}
Run that in our rails console, and good things happen. Seems like we have some random users from my (small) database.
{% highlight ruby %}
[{:id=>1, :detail=>{:username=>"adam5"}},
{:id=>2, :detail=>{:username=>"adam1"}},
{:id=>3, :detail=>{:username=>"adam11"}},
{:id=>4, :detail=>{:username=>"adam5"}}]
{% endhighlight %}
Let's move that code into a controller action.
{% highlight ruby %}
def create
contacts = [{:id => 1}, {:id => 2}, {:id => 3}, {:id => 4}]
contacts.each do |c|
user = User.order('random()').first
c[:detail] = {:username => user.username}
end
render :json => contacts, :root => false
end
{% endhighlight %}
Uh-oh. This time, we get a decidedly un-random response:
{% highlight javascript %}
[
{
"id": 1,
"detail": {
"username": "adam6"
}
},
{
"id": 2,
"detail": {
"username": "adam6"
}
},
{
"id": 3,
"detail": {
"username": "adam6"
}
},
{
"id": 4,
"detail": {
"username": "adam6"
}
}
]
{% endhighlight %}
Looking at the logs, we'll see this:
{% highlight bash %}
User Load (0.7ms) SELECT "users".* FROM "users" ORDER BY random() LIMIT 1
User Load (0.7ms) SELECT "users".* FROM "users" ORDER BY random() LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" ORDER BY random() LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" ORDER BY random() LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" ORDER BY random() LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" ORDER BY random() LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" ORDER BY random() LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" ORDER BY random() LIMIT 1
{% endhighlight %}
Rails caching, normally so useful, causes a problem in this situation. No sweat. You just need to use ActiveRecord's uncached method.
Modifying the action to use uncached looks like this:
{% highlight ruby %}
def create
contacts = [{:id => 1}, {:id => 2}, {:id => 3}, {:id => 4}]
contacts.each do |c|
User.uncached do
user = User.order('random()').first
c[:detail] = {:username => user.username}
end
end
render :json => contacts, :root => false
end
{% endhighlight %}
The database query no longer gets cached for the duration of the "User.uncached" block, and a new query is executed for each iteration. The controller action now gives us some nice, randomized output.
{% highlight javascript %}
[
{
"id": 1,
"detail": {
"username": "adam3"
}
},
{
"id": 2,
"detail": {
"username": "adam3"
}
},
{
"id": 3,
"detail": {
"username": "adam4"
}
},
{
"id": 4,
"detail": {
"username": "adam1"
}
}
]
{% endhighlight %}


Unity is platform for making real-time 3D projects for Games, Animation, Film, Transportation, Architecture, Engineering, Manufacturing & Construction provided as a native, desktop application for Windows, Mac and Linux.
PWA is a type of application software delivered through the web, built using common web technologies including HTML, CSS and JavaScript that runs in any browser on any operating system.
cons are dependent on the project itself
It's not about Unity vs Web App, it's about your project: if it fits to Web or not.
If your app is a simple design with simple, less complicated features, go for a web app. If it's a complicated application with sizeable graphics and animations or multiple motion events with WOW affect, then go for Unity.
The cost effectiveness of web apps makes it a better runner for non WoW affect apps but if you are looking for features that are out of the ordinary, Web App may not be the answer.


Introduction
Graphyte is a general-purpose webdoc automation engine that supports the full project lifecycle (requirement capture, revision, design, development, Q&A, documentation). It helps automate the creation of interactive, portable web documents that massively reduce the size and complexity of traditional documentation.
Features:
- Generation of dynamic web documentation.
- Interactive visualization of configuration and text files.
- Markup syntax for highlighting parameters in TXT, XML files.
- Support for diagrams in SVG format and in UML language.
- Version control.
- Integrated text editor for template review.
- Parameter extraction and validation.
- Minimum overhead per new revision of the documentation.
As a general purpose documentation tool, the range of possible applications is unlimited:
- Cisco NSO project requirements / versioning / validation / design / reference.
- Network designs/LLD documents with device configurations.
- Interactive presentations
- Flow/Sequence/Component diagrams with supporting documents.
- Review of design specifications maintaining version control.
- etc
Models and Modules
Graphyte requires a set of input files from the user. In turn, it generates and validates a standalone web based set of documents known as the graphyte model.
A model is a set of web documents that are related to each other, and combined create the full representation of the target design the user is trying to build. It could be a series of network schematics with device configurations, a sequence diagram with extended information, a logic workflow and parametrized templates for an automation project, or your new flat's blueprints and notes.
Each one of the HTML web documents that assemble the model is referred to as a graphyte module. A model may consist of one or more modules. The web page layout of a module has the following structure:
Input Files
In order to generate a model using Graphyte, the user needs to prepare a series of source files to be passed as inputs:
- Templates: These are text files with content that will show up in the viewer when triggered by mouse clicks on the diagram. The currently supported formats are Plain Text files (.txt), eXtensible Markup Language XML files (.xml) and Comma Separated Values files (.csv).
- Diagrams: The diagram files used with graphyte are also text-based. Currently supported formats are Unified Modeling Language UML (.uml) and Scalable Vector Graphics files (.svg). UML file support is achieved by graphyte via integration with the PlantUML tool. SVG is an XML-based image format for two-dimensional graphics. A variety of applications allow creating or exporting to SVG files, including Inkscape or Microsoft Visio.
- Variable List: Optionally, depending on which graphyte features the user is aiming for, additional input files may be needed. This is the case for example for input files with parameters, that graphyte can automatically validate against a user defined list of allowed model parameters.
- graphyte.conf file: The user is required to include a small configuration file where a series of options can be set, including the name and version of the model.
Templates
The ultimate objective of a model is to represent relevant information in the viewer area responding to user events (mouse clicks) on the different parts of the diagram.
This relevant information is provided to graphyte in the form of text files called templates.
Templates may optionally include parameters. Graphyte provides syntax capabilities to support up to 4 types of parameters that will be detected, processed and highlighted as such.
The section Creating Templates has all the details on how to create graphyte templates.
Diagrams
Graphyte diagrams allow the model designer to represent large amounts of information in a usable and condensed way.
Graphyte supports three types of input diagrams:
- SVG: Scalable Vector Graphics files (with extension .svg).
- UML: Unified Modeling Language UML files (with extension .uml)
- YANG: YANG modeling languaje files (with extension .yang)
Both are processed and embedded into the HTML modules as SVG objects (UML diagrams are internally converted to SVG). SVG files are text-based specifications of two-dimensional graphics, written following an XML-based structure. Rendering of most SVG graphics is supported by the majority of mainstream modern browsers (W3C). Other advanced features present in complex SVG elements, like for example foreign-object elements are not currently supported in the HTML5 <svg>
element. Test HTML support for your diagrams passing them to the graphyte tool.
Both types of diagram specifications are text-based and require a rendering engine to create the resulting graphics. Below are a couple of examples of the source text file and the rendered version:
Within the diagram, the model designer will link shapes or elements to target templates. By doing this, the shape becomes responsive to mouse clicks that will load the target template into the viewer.
The creation of SVG graphics is usually achieved by using a graphic editor. One can simply draw lines and shapes and once ready export the work to an SVG file. We will explain how to do this using several well-known editors:
- Visio, a widely used software from Microsoft.
- Draw.io, an online flowchart editor.
- Inkscape, a free vector graphics editor.
The following sections provide the necessary details for creating graphyte-ready SVG/UML diagrams.
- Creating SVG diagrams with Microsoft Visio
- Creating SVG diagrams with Draw.io
- Creating SVG diagrams with Inkscape
- Creating UML diagrams for Graphyte
- Rendering YANG diagrams with Graphyte
Variable List
As previously mentioned, graphyte templates may include variables, which are marked using a specific available syntax.
Optionally, the model designer may choose to perform automatic validation of template variables against a pre-defined input list, provided in .xls/.xlsx sheet format. This will help ensure that all variables used in templates are known and valid.
Visit the Variable List section section for details on how to create the variables worksheet.
Configuration File
Finally, graphyte requires a configuration file that will contain the details of the model such as name and version, as well as other optional fields. The graphyte.conf file is mandatory and must be unique.
Find the details for the creation of graphyte.conf file on Configuration File section.
Output Files
Once the input files are ready, the model owner is ready to run graphyte (see Running Graphyte section for details).
As a result, the model, consisting on one or more HTML modules, will be generated. Details on the resulting files can be found on the section Graphyte Output Files: The Model.


| Still haven't recieved them so it must be something that you have on your computer, viruses of some kind for i get email all the time from everyone else. check your firewall.it could be that it is not letting your emails out or have someone do a virus removal and if they have to do a complete disk wipe then you need to save what files you really need to save onto disk and clear the rest and hope that there is no viruses in those files. Marvin Gates |


Danilo Kim
About
Portfolio
Contact
Portfolio
Hangman
RPG Game
Trivia Game
Rutgets Info Widget
Rock Paper Scissors
Connect with Me


The sample demonstrates construction of complicated view that allows editing data base objects and displays calculation values for nested entities.
This example also demonstrates a simple way to create cascading dropdowns.
Original example: http://knockoutjs.com/examples/cartEditor.html


Pim Mulierloop 15 km
Santpoort NED
Race Winners
(74 runnings for men, 54 runnings for women)
20 May
2007
28 May
2006
29 May
2005
30 May
2004
27 Oct
2002
28 Oct
2001
29 Oct
2000
24 Oct
1999
25 Oct
1998
26 Oct
1997
17 Nov
1996
05 Nov
1995
06 Nov
1994
07 Nov
1993
05 Sep
1992
1991
04 Nov
1990
15 Oct
1989
16 Oct
1988
18 Oct
1987
19 Oct
1986
19 Oct
1985
14 Oct
1984
16 Oct
1983
1982
18 Oct
1981
12 Oct
1980
21 Oct
1979
19 Mar
1978
27 Mar
1977
14 Mar
1976
16 Mar
1975
16 Mar
1974
24 Oct
1965
25 Oct
1964
27 Oct
1963
21 Oct
1962
15 Oct
1961
09 Oct
1960
04 Oct
1959
05 Oct
1958
13 Oct
1957
1956
09 Oct
1955
10 Oct
1954
04 Oct
1953
05 Oct
1952
07 Oct
1951
24 Sep
1950
30 Oct
1949
31 Oct
1948
1944-47
---
26 Mar 1939
12:57.2 13 Feb
1938
17 Jan
1937
Notes: 1937 was the inaugural year. The 1939, 1948, and 1952 races were
held in Velzen; the 1942 race was held in Beverwijk; the 1965 race was from
Haarlem to Velzen.
29 May
2016
10 mile
59:07
Joost
vanGaalen-2
10 mile
1:11:18
Miranda
Rijsdijk (NED)
31 May
2015
10 mile
59:11
Joost
vanGaalen (NED)
10 mile
1:08:50
Lineke Kroon-3
25 May
2014
10 mile
1:05:11
Wieger Poeze
(NED)
10 mile
1:23:36
Lonneke
vanSchaik (NED)
26 May
2013
15 km
54:54
Emiel Pieterse
(NED)
15 km
1:01:37
Lineke Kroon-2
20 May
2012
15 km
56:37
Jeroen Plevier (NED)
15 km
1:03:39
Lineke Kroon (NED)
22 May
2011
15 km
52:04
Michael Woerden-3
15 km
1:00:01
Esther vanHeerde (NED)
16 May
2010
15 km
51:34
Michael Woerden-2
15 km
56:44
Helen Sharpe (NED)
24 May
2009
15 km
50:55
Michael Woerden (NED)
15 km
1:02:44
Marianne vanderLinden-2
25 May
2008
15 km
49:32
Wim Padmos-2
15 km
1:00:40
Esther Kalkman-2
15 km
50:15
Wim Padmos (NED)
15 km
1:04:40
Esther Kalkman (NED)
15 km
50:51
David Knappstein (NED)
15 km
1:04:14
Ingrid Dekker-2
15 km
52:26
Jeffrey Sullivan
15 km
1:04:21
Ingrid Dekker (NED)
15 km
47:47
Rachid Mohammadi-3
15 km
59:59
Monique Arkenbout (NED)
15 km
---
Rachid Mohammadi-2
15 km
55:33
Wendy Vlaming (NED)
15 km
---
n/a
15 km
---
n/a
15 km
44:53
John Kipchumba Rotich (KEN)
15 km
50:41
Christine Chepkonga (KEN)
15 km
45:58
Theo VandenAbbeel (BEL)
15 km
52:31
Wilma vanOnna (NED)
15 km
48:03
Rachid Mohammadi (NED)
15 km
51:08
Irma Heeren (NED)
15 km
46:54
Vladimir Tonchinski (BLR)
15 km
52:13
Nadezhda (Wijenberg)
Ilyina (RUS)
15 km
45:22
Vladimir Gusev (KAZ)
15 km
57:27
Nicole Dassen (NED)
15 km
46:42
Jan-Dirk Hazeleger (NED)
15 km
51:28
Anne vanSchuppen (NED)
15 km
46:27
Kipsubei Kosgei (KEN)
15 km
52:50
Natalya Sorokivaskaya (KAZ)
15 km
50:18
Johan Smet (NED)
15 km
56:06
Philomena Vrancken-2
15 km
---
n/a
15 km
54:57
Philomena Vrancken (NED)
---
---
n/a
---
---
n/a
15 km
48:48
nfn vanDiepen (NED)
15 km
59:26
Ine Bakker (NED)
15 km
---
n/a
15 km
---
n/a
15 km
---
n/a
15 km
---
n/a
15 km
49:16
Edwin Aardenburg (NED)
15 km
54:09
Marianne vanderLinden (NED)
Hf Mar
---
n/a
---
---
n/a
20 km
1:08:14
Gerard vanLent (NED)
10 km
44:45
C Helder (NED)
---
---
n/a
---
---
n/a
20 km
1:10:14
Jan Sinnige (NED)
10 km
37:38
Olga Commandeur (NED)
20 km
1:06:31
Willem Westerholt (NED)
10 km
41:07
Marijke Abrahamse (NED)
20 km
---
n/a
---
---
n/a
20 km
1:04:37
Rob Strik (NED)
20 km
1:35:50
nfn Feringa (NED)
20 km
1:07:26
Conno duFosse (NED)
---
---
n/a
28 Oct
1978
---
---
n/a
---
---
n/a
---
---
n/a
---
---
n/a
9.0 km
29:01.0
Evert vanRavensberg (NED)
3.05 km
11:12.2
Marisca Zethof (NED)
9.35 km
---
Theo Verneek (NED)
3.1 km
---
Tineke Kluft (NED)
9.35 km
26:43.0
Leonard Frederiks (NED)
3.1 km
9:46.6
Joke (vanderStelt)
vanGerwen-3
9.37 km
26:52.6
Geert Jansen (NED)
3.1 km
11:02.5
Sjouke Dijkstra (NED)
12 Nov 1972
6.0 km
---
nfn Hopman (NED)
2.0 km
---
n/a
24 Oct 1971
6.0 km
17:10.2
Wim vanGerwen-2
2.0 km
6:13.4
Joke (vanGerwen) vanderStelt-2
18 Oct 1970
5.5 km
16:24.2
Wim vanGerwen (NED)
2.0 km
5:54
Joke (vanGerwen)
vanderStelt (NED)
26 Oct 1969
5.5 km
16:45.4
Wim Barsingerhorn (NED)
2.0 km
6:28.0
Tilly vanderMade-2
20 Oct 1968
5.5 km
---
Alfred Moser (SUI)
2.0 km
---
Marijke (Moser) deGraaf (NED)
22 Oct 1967
5.5 km
---
A Blok (NED)
2.0 km
---
Tilly vanderMade (NED)
06 Nov 1966
5.5 km
15:47.4
C Nelis (NED)
1.5 km
4:30.0
Ilja Laman-2
7.5 km
28:28
Piet Beelen (NED)
1.5 km
4:20
Ilja Laman (NED)
---
---
n/a
---
---
n/a
5.4 km
15:09.8
Jaap Evers-3
1.5 km
4:28.6
Thea Lammertink-Seure-2
5.37 km
15:40.0
Jaap Evers-2
1.5 km
4:24.5
Thea Lammertink-Seure (NED)
5.37 km
16:01.8
Jaap Evers (NED)
5.37 km
16:30.4
Jan-Willem Keesom-3
5.37 km
16:40.8
Jan-Willem Keesom-2
5.37 km
16:01.8
Jan-Willem Keesom
---
---
n/a
---
---
n/a
----
13:18.0
nfn Borst-3
4.5 km
13:51.4
nfn Borst-2
3.74 km
11:46.8
nfn Koning (NED)
3.74 km
11:48.8
nfn Borst (NED)
4 km
11:50.0
nfn Adrichem (NED)
4 km
12:06.3
nfn Hopman (NED)
4 km
14:09.6
Hoogschagen vanDoves (NED)
3.5 km
13:15.0
Wim Slijkhuis (NED)
---
---
not held
27 Sep
1943
---
---
n/a
19 Apr
1942
3.5 km
11:44.3
Frits deRuyter-2
1941
---
not held
31 Mar 1940
4 km
12:05.8
Frits deRuyter (NED)
4 km
J Meyer
---
11:07
M deGroot-2
5 km
18:22.2
M deGroot (NED)
Most Wins
(1937/date)
Men
3
nfn Borst (NED)
1952,1954-55
Jaap Evers (NED)
1961-63
Rachid Mohammadi (NED)
1998,2002,2004
Michael Woerden (NED)
2009-11
Women
3
Joke vanGerwen vanderStelt (NED)
1970-71,1975
Lineke Kroon (NED)
2012-13,2015
Prize Money (ADR qualified runners) Year Men Women Total 1998 n/a $355 $355
Race Time Bias
(sec/km)
Insufficient data to calculate the race time bias.
Competitive Level
(1990-date)
Insufficient data to calculate the competitive level.
Quality Performances
Men <45:00 2 <45:20 2 <45:40 3 <46:00 4 Women <51:00 1 <51:30 3 <52:00 3 <52:30 5 <53:00 7 <53:30 8 <54:00 10
Contributors: Paul Michiels (50), Juraj Gasparovic (42), Klaas Loonstra (22)


得分如下： 勝-2分, 和-1分, 負-0分, 加時或最後十二碼球勝 - 4分(不包括倍積分和不適用於決賽)。
1) Rank the 8 playoff teams according to your estimate of their (descending) order of finish.
2) Rank your winner 1st, 2nd, 3rd and 4th ... etc. Your first-ranked team receives 8x2 points for each win, 8 for a draw in a 90mins game, additional 4 points if win in OT/penalty (not apply in the final game). Second-ranked team 7x2 points for each win and 7 for a draw in a 90mins game, additional 4 points if win in OT/penalty (not apply in the final game). Points for each win ... eight-ranked team - 1x2 point for each win. 1 for draw in a 90mins game, additional 4 points if win in OT/penalty (not apply in the final game). There will be 10 bonus points for correctly ranking the UEFA winner (ranked first). Another 10 bonus points each for correctly ranking Arsenal/Chelsea playing in UEFA Europa League. $5 per entry, maximum 4 entries.
3) Please pass on to interested parties. Make payment to Albert Li. Etransfer is also accepted (email: lialbert298@gmail.com). Your picks must be in no later than 2:00pm April 9. 1st game starts on April 9th till June 3rd.
4) Prizes:
If <25 play, 1st wins 100% prize of the pool; last place finisher gets back $5 from the first place prize money.
If 25/+ play, will create a 2nd prize, 1st wins 70% prize of the pool; 2nd wins 30%; last place finisher gets back $5 from the first place prize money.
If 35/+ play, there will be a 3rd prize, 1st wins 60% prize of the pool; 2nd wins 30%; 3rd wins 10%; last place finisher gets back $5 from the first place prize money.
“Ties Split” Rule applies. If 2 players tie for a given prize, they split that prize and the next (lower) prize combined.
2019 歐聯估估赢大錢，参加注意事項。
1) 順序由最高起，列出八隊的排名位置
2) 得分如下： 勝-2分, 和-1分, 負-0分, 加時或最後十二碼球勝 - 4分(不包括倍積分和不適用於決賽)。最高排名隊得8倍積分，第二高排名得7倍。如是者往下推。
估中冠軍隊，奖十分。
估中阿仙奴隊於歐联賽最後排名位置, 奖十分。
估中車路士隊於歐联賽最後排名位置, 奖十分。
3) 有興趣参加者，請將你的選擇，於四月九日下午2点前提交，付款給拔哥。可以etransfer, email<EMAIL_ADDRESS>4) 每注$5, 最多可下4注
5) 彩金分配如下：
若少過25注，則第一名獲100％彩池獎金; 包尾者取回本金，由第一名彩金扣出。
25注到35注之間，会設有二奖, 則第一名獲70％彩池獎金; 第二名獲30％。包尾者取回本金，由第一名彩金扣出。
若多過35注，会設有三奖, 第一名獲得60％彩池獎金;第二名獲30％;第三名獲10％。包尾者取回本金，由第一名彩金扣出。
平分勝出，則平均分配得奖位置及其順序之彩金


About Me:
Hello, I'm Josh and welcome to my website!
I guess I'll add a little bit about me.
I'm from New Plymouth and have lived there most of my life, although I have lived in Tauranga when I was 3 and Chile
for a month when I was 16.
My main hobbies include coding and Inline Hockey, I started learning how to code in highschool and that's what
inspired me to do the Dev Academy course. I started playing Inline Hockey when I was 7 and have played it ever since.
I have represented my country twice in 2013 and 2016. In 2013 I played in the Junior Olympics and World Championships
in Los Angeles for the Under 14 New Zealand Team which was amazing and in 2016 I played the same two tournaments in Hawaii
for the Under 18 New Zealand Team.
I now live in Wellington with 5 other flatmates in Newtown and I am looking forward to doing the Dev Academy course
and then eventually gaining a job in the tech-industry.


Problem 2. People of age
Write a function that checks if an array of person contains only people of age (with age 18 or greater)
Use only array methods and no regular loops (for, while)
You could use Chrome console (F12) or Firebug to see the results.


Techday, 2016-11-11
David Luposchainsky
quchen /ˈkuːχn̩/
TNG Technology Consulting
data Atom = Atom { _element :: String
, _point :: Point }
data Point = Point { _x :: Double
, _y :: Double }
Let's move an atom to the right.
pushAtomRight :: Atom -> Atom
pushAtomRight (Atom e (Point x y)) = Atom e (Point (x + 1) y)
pushAtomRight2 a = a { _point = (_point a) { _x = _x (_point a) + 1 }}
makeLenses ''Atom
makeLenses ''Point
pushAtomRight' :: Atom -> Atom
pushAtomRight' = over (point . x) (+ 1)
makeLenses ''Atom
makeLenses ''Point
Generates:
element :: Lens' Atom String
point :: Lens' Atom Point
x :: Lens' Point Double
y :: Lens' Point Double
(.) :: (b -> c) -> (a -> b) -> (a -> c)
can be specialized to
(.) :: Lens b c -> Lens a b -> Lens a c
point :: Lens' Atom Point
x :: Lens' Point Double
point . x :: Lens' Atom Double
view (_1 . _2) ((True, "Hello"), "World")
==>
"Hello"
over (_1 . _2) length ((True, "Hello"), "World")
==>
((True, 5), "World")
(over _1 length . over _2 length) ("Hello", "World")
==>
(5, 5)
= “Multi-lenses”: focus on multiple elements
over both
length
("Hello", "World")
==>
(5, 5)
over (both . _2)
length
((True, "Hello"), (False, "World"))
==>
((True,5), (False,5))
over (traverse . both)
length
[("Hello", "World"), ("TNG", "Techday")]
==>
[(5,5),(3,7)]
toListOf (traverse . both . to (++ "!"))
[("Hello", "World"), ("TNG", "Techday")]
==>
["Hello!","World!","TNG!","Techday!"]
“What is a lens for the content of a Just?”
over _Just (2^) (Just 8) ==> Just 256
over _Just (2^) Nothing ==> Nothing
“Touch matching values, ignore others”
over (traverse . _Right)
(2^)
[Left "Hello", Right 4, Right 8, Left "World"]
==>
[Left "Hello", Right 16, Right 256, Left "World"]
over (traverse . _Left . _head)
toLower
[Left "Hello", Right 4, Right 8, Left "World"]
==>
[Left "hello", Right 4, Right 8, Left "world"]
view (_Left . _Just) (Left (Just 3))
==>
3
review (_Left . _Just) 3
==>
Left (Just 3)
"00:00:00" & upon (tail.tail).partsOf (filtered (== '0')) .~ "1234"
"00:12:34"


Table of Contents
- 1. #coq
- 1.1. Proof General pg coq
- 1.2. Resources
- 1.3. Coq Libraries
- 1.4. Papers
- 1.5. Ltac Semantics, History, and Future
- 1.6. Managing Coq installations
- 1.7. VST vst
- 1.8. Coq coq
- 1.8.1. Is there a way to force Coq to treat names as constructors errors
- 1.8.2.
nat
and large numbers errors - 1.8.3. Set vs. Type theory
- 1.8.4.
Variable
andGeneralizable Variable
typeclasses - 1.8.5. Real Numbers in Coq reals numbers
- 1.8.6.
{| ... |}
vs{ ... }
typeclasses - 1.8.7.
debug auto
tactics auto - 1.8.8. Prop vs. bool theory
- 1.8.9.
cbn
tactics - 1.8.10.
cbv
tactics - 1.8.11. TODO
dependent induction
tactics - 1.8.12. Search search
- 1.8.13. TODO Module types modules
- 1.8.14. TODO Hypothesis sections
- 1.8.15. TODO Module Advantages / Disadvantages modules
- 1.8.16. TODO Module parameters / instantiation modules
- 1.8.17. TODO Hint Ordering / Priority auto hints
- 1.8.18. TODO Reordering subgoals goals
- 1.8.19. Destruct notations notation
- 1.8.20.
pattern term
tactics - 1.8.21. TODO Custom induction principles induction
- 1.8.22. TODO Destructing multiple existential variables destruct
- 1.8.23. Ltac naming ltac
- 1.8.24. TODO Instance / Program Instance instance program_instance
- 1.8.25. Decidable equality and conditionals dec_eq
- 1.8.26. UIPDec dec_eq
- 1.8.27. TODO Generators qc
- 1.8.28. TODO Extrinsic / intrinsic verification
- 1.8.29. Minifier tools
- 1.8.30. TODO Module Functors modules
- 1.8.31. TODO Sigma types sigma
- 1.8.32. TODO
..
problems in PG bugs - 1.8.33. Replacing with A:=B set
- 1.8.34. Coqtop bugs
- 1.8.35. ProofGeneral saving contents of buffers pg
- 1.8.36. ProofGeneral look up information about identifier pg
- 1.8.37. In Depth Semicolons
- 1.8.38. TODO InvertN tactics
- 1.8.39. TODO coq-compile-before-require pg
- 1.8.40. Ltac Debugging in Proof General ltac debugging pg
- 1.8.41. Inversion subst warning ltac tactics best_practices
- 1.8.42. Ltac bug fixing ltac
- 1.8.43. Redefining Ltac ltac
- 1.8.44. TODO Cut tactics
- 1.8.45. Refine vs Exact tactics
- 1.8.46. TODO Unshelve tacticals
- 1.8.47. Congruence tactic
- 1.8.48.
||
and+
ltac tacticals - 1.8.49. Progress tactics
- 1.8.50. Extraction extraction
- 1.8.51. Undocumented tactics as of 8.5 tactics documentation
- 1.8.52. Is there a way to turn off notations when printing? notations
- 1.8.53. TODO Functional induction tactics induction
- 1.8.54. match reverse ltac
- 1.8.55. Notations for repeated patterns (like lists) notation
- 1.8.56. Proof with tactics
1 #coq
1.1 Proof General pg coq
Proof general is an emacs interface to a number of proof assistants. In particular it works quite well with Coq!
1.1.1 Coq has frozen in proof general
Use C-c C-x
to kill coqtop
.
If all else fails you can kill the coqtop
process externally.
1.1.2 Use company coq
Company-coq is an Emacs mode on top of proof general which provides a lot of useful additions. It prettifies symbols (which can be turned off), it provides a lot of completions which can be very useful when discovering tactics, and it provides easy ways to look up types and documentation.
1.1.3 MELPA?
Proof general is not on MELPA as of writing, but the plan is to have a MELPA package once the new proof general is out of beta.
1.2 Resources
- https://math-comp.github.io/mcb/book.pdf
- ssreflect book.
- http://ilyasergey.net/pnp/
- another ssreflect book.
- http://www.cs.bham.ac.uk/~mhe/GeneralizedHedberg/html/GeneralizedHedberg.html
- Hedberg's theorem in Agda. Relevant to decidable propositions.
- https://quanttype.net/posts/2016-04-19-finding-that-lemma.html
- How to search in Coq.
- https://coq.inria.fr/distrib/current/refman/language/gallina-extensions.html?highlight=sections#section-mechanism
- Manual page about sections.
- https://github.com/uwplse/CoqAST
- Toy Coq 8.5 plugin.
- https://coq.inria.fr/distrib/current/refman/proof-engine/ltac.html
- Chapter on Ltac in the reference manual.
- Lots of ways to combine tactics.
;
,+
,||
- https://github.com/lemonidas/invertn_tactic
- Ocaml tactic for inverting a hypothesis and creating at most
n
new hypothesis.
- Ocaml tactic for inverting a hypothesis and creating at most
- https://github.com/ppedrot/ltac2
- Ltac2, a new tactic language
- https://coq.inria.fr/cocorico/Home
- Coq wiki. Seems to have moved to Github: https://github.com/coq/coq/wiki
- http://iris-project.org/
- Higher-Order Concurrent Separation Logic Framework implemented and verified in the proof assistant Coq.
- Somewhat similar to VST
1.3 Coq Libraries
- https://madiot.fr/coq100/
- Common mathematical theorems implemented in Coq.
- https://gitlab.mpi-sws.org/robbertkrebbers/coq-stdpp
- Larger standard library for Coq.
- https://github.com/coq-contribs/coq-contribs.git
- User submitted coq libraries.
- Superseded by installing libraries with opam.
- https://github.com/uwplse/StructTact
- Utility and tactic library.
- https://github.com/wilcoxjay/tactics
- Small tactic library.
1.4 Papers
- https://pdfs.semanticscholar.org/0aba/4e4000988d8563c2e64b343f876efa77767b.PDF
- Paper on Pollack-inconsistency. Related to the thought that you should not be able to think that a theorem which is false has been proved true. Relevant to parsing and printing in proof assistants.
- Some slides: https://www.cs.ru.nl/~freek/talks/rap.pdf
1.5 Ltac Semantics, History, and Future
1.5.1 Old Semantics of Ltac
- http://www.ii.uni.wroc.pl/~wjedynak/publications/master.pdf
- Study of the semantics of Ltac
- Out of date as 8.5 introduced a new tactics engine
- http://dl.acm.org/ft_gateway.cfm?id=2505890
- Another paper on the semantics of Ltac
1.5.2 More Modern Ltac Information
1.5.3 Papers on the Inception of Ltac
1.6 Managing Coq installations
1.6.1 Switching between versions versions coq
You may find yourself wanting to switch between versions of Coq. There are a couple of options for this:
- opam switch
- the nix package manager
- GNU stow
1.7 VST vst
1.7.1 entailer and cancel tactics vst
VST has the tactics entailer
and entailer!
, which are used to
solve separation logic goals of the form `_ |– _`.
The difference between entailer
and entailer!
is that the
latter uses a heuristic, so it can solve the goal faster. Usually
you try entailer!
, and if it doesn't work you try entailer
.
If it does not work,see if you can rewrite the goal to get
something of the form A |-- A
. If your goal is exactly A |--
A
, then you can use the tactic cancel
, which is to entailer
what reflexivity
is to auto
.
1.7.2 entailer vs forward tactics vst
If your goal has Entail
or _ |-- _
, then you likely use entailer
, or entailer!
.
If your goal has semax
, then you do forward
.
1.7.3 Strongest Post Condition Principle
VST is using the strongest post condition principle.
https://en.wikipedia.org/wiki/Predicate_transformer_semantics#Strongest_postcondition
Strongest postcondition means if you go forward in the program from this precondition, with this instruction I can be sure to end up in this postcondition.
Weakest precondition is going backward in the sequence of the program. From this postcondition, if we applied this instruction c, I can assume this properties where true before applying this c.
The advantage of the forward approach is that it is very close to symbolic execution, with things such as assignment.
1.8 Coq coq
1.8.1 Is there a way to force Coq to treat names as constructors errors
This question is asking if there is a mechanism in Coq for treating
constructors differently, similar to in Haskell. In Haskell you are
forced to use capital letters at the beginning of every
constructor's identifier. This makes it so when pattern matching
the compiler can easily distinguish between what looks like a
constructor, and what should be a variable (everything that starts
with a lower case letter). This can be useful for avoiding mistakes
where you think you're matching on a specific constructor, say C
,
but are instead matching on all constructors and assigning it to a
variable c
.
Coq has no mechanism for making these distinctions, but you will often get error messages like…
Error: This clause is redundant.
Since the variable match could be redundant.
1.8.2 nat
and large numbers errors
Large natural numbers may cause segfaults, since they can't fit in
memory. The unary representation is really inefficient. In
real-world Coq developments you may want to use more efficient
representations, like Z
instead.
1.8.3 Set vs. Type theory
Set
is smaller than Type
, since Set : Type
.
Put non-propositional things (things you want to extract) in Set
where possible.
(why? Ask Johnw)
http://adam.chlipala.net/cpdt/html/Cpdt.Universes.html https://sympa.inria.fr/sympa/arc/coq-club/2010-04/msg00092.html https://people.cs.kuleuven.be/~bart.jacobs/coq-essence.pdf
1.8.4 Variable
and Generalizable Variable
typeclasses
Generalizable Variables
has nothing to do with Variable
.
Generalizable Variables
says "allow the following variables to
be automatically introduced by `{...}
".
Variable
introduces a new axiom with the given name into the
scope that will be added as a parameter at the end of a section.
1.8.5 Real Numbers in Coq reals numbers
For real analysis in Coq there are a few libraries:
- Computational, CoRN: https://github.com/c-corn/corn
- Fast real computationns in coq: http://coq-interval.gforge.inria.fr/
- Friendly real number library: http://coquelicot.saclay.inria.fr/
1.8.6 {| ... |}
vs { ... }
typeclasses
These both introduce dependent records, and should be the same.
1.8.7 debug auto
tactics auto
Using debug auto
will show you what auto is doing.
1.8.8 Prop vs. bool theory
Some people prefer the use of bool
for decidable propositions
over Prop
, since if it's decidable you can have a boolean
function which automatically decides the proposition. This is
better for manipulating the proposition, excluded middle is
immediate, and you can program with it "natively". Prop
and
bool.
You should also be able to convert to Prop if necessary.
1.8.9 cbn
tactics
"call by name"
https://coq.inria.fr/distrib/current/refman/proof-engine/tactics.html#coq:tacn.cbn
Meant to be a more predictable replacement for simpl
.
1.8.10 cbv
tactics
1.8.11 TODO dependent induction
tactics
[19:40:28] <jwiegley> @rhd You often need dependent induction when a type dependent on a term you’ve destructed. [19:40:54] <jwiegley> @rhd beware, it will induce a dependency on the axiom JMeq, and can in most cases be avoided (although sometimes requiring a considerable amount of work) [19:41:45] <antalsz> @jwiegley I don’t have a good intuition for when it’s really necessary, though – any tips on that? [19:41:57] <antalsz> Usually when I’ve tried it it’s because nothing else is working and it isn’t what I really want [19:41:58] <jwiegley> If you use vector for any length of time, you’ll run into it fairly readily [19:42:03] <jwiegley> I have a cute example if you like [19:42:16] <rhd> according to `Print Assumptions` the uses of it in Semantics.v don't involve JMeq [19:42:17] <antalsz> much like turning on `-XImpredicativeTypes`, it seems to be a symptom of me going terribly wrongheaded along the way [19:42:18] <rhd> which is weird [19:42:33] <rhd> or maybe I'm wrong about what `Print Assumptions` says [19:43:13] <jwiegley> @rhd Nice, sometimes (though rarely) it can do its work without the axiom. [19:44:03] <jwiegley> @antalsz https://github.com/jwiegley/category-theory/blob/master/Instance/Two.v#L69 [19:44:08] <rhd> i guess it also retains equalities for you about the indices(?) of the dependent type you're doing induction on [19:44:38] <jwiegley> Edit that line to change the semicolon to . Then if you try to destruct f, you’ll get the error that indicates (usually) that dependent induction will work. Which it will, and easily solve the goal here. You can see the custom inversion lemma I’m using here to avoid it. [19:45:08] <jwiegley> This is a case where using dependent destruction results in the following assumption: [19:45:08] <jwiegley> ```Axioms: [19:45:08] <jwiegley> JMeq_eq : ∀ (A : Type) (x y : A), x ~= y → x = y [19:45:08] <jwiegley> ``` [19:46:02] <rhd> https://github.com/uwplse/StructTact/blob/master/StructTactics.v#L517-L523 This tactic does something similar to help you track the actual values of indices [19:46:08] <jwiegley> @rhd It can introduce heterogeneous equalities (via the axiom, when needed) which gives it a lot of additional power.
1.8.12 Search search
Can search for notations by putting double quotes around the notation. This can be unexpected when notations are used to essentially just rename functions. E.g.,
Notation open e1 e2 := (open_exp_wrt_exp e1 e2).
More info on search:
https://quanttype.net/posts/2016-04-19-finding-that-lemma.html
Can be very helpful to search for conversions between data types, like so:
Search (nat -> Z).
This snippet will find functions which convert between `nat` and `Z`.
1.8.13 TODO Module types modules
[21:14:03] <chobbes> So, a module type ends up being kind of similar to an abstract class if you squint? [21:15:03] <tsibutpi> yes but I think modules aren't first class [21:15:05] <antalsz> More like an interface, I think, but there’s still a lot of squinting. [21:15:33] <chobbes> @antalsz an abstract interface :stuck_out_tongue:? [21:16:07] <pmetzger> So it’s a lot more than the sort of modules you find most imperative languages. It is parameterized.
1.8.14 TODO Hypothesis sections
[21:20:50] <graydon> in Sequences.v, I see: [21:20:56] <graydon> Hypothesis R_functional: [21:20:56] <graydon> forall a b c, R a b -> R a c -> b = c. [21:21:24] <graydon> is that declaring a prop without providing a proof? like is that equivalent to "assume this is true, trust me"? [21:22:55] <antalsz> @graydon Yeah, kind of – but not quite [21:23:12] <antalsz> `Hypothesis` indeed does that, except that if you look at the top of the file it starts `Section SEQUENCES.` [21:23:46] <antalsz> That means that at the end of the section (`End SEQUENCES.`, at the bottom of the file), all the hypothesis and variables and such become _arguments_ to all the necessary values defined inside the section [21:24:41] <antalsz> So basically, everything after the `Hypothesis R_functional` declaration gets to assume that `R` is functional, but when the section ends they’ll require an extra argument proving that `R` is indeed functional [21:25:16] <graydon> ah, so then [21:25:19] <graydon> Lemma cstep_functional: [21:25:23] <graydon> is providing it, implicitly? [21:25:29] <graydon> (in Semantics.v) [21:26:00] <antalsz> Hmm… not quite? [21:26:06] <graydon> (presumably this is all done via implicit arguments, since nobody seems to mention it) [21:26:13] <antalsz> Not quite [21:26:37] <antalsz> In `Semantics`, check the type of `finseq_unique` [21:26:56] <antalsz> In `Sequences`, it’s given as```Lemma finseq_unique: [21:26:56] <antalsz> forall a b b', [21:26:56] <antalsz> star a b -> irred b -> [21:26:56] <antalsz> star a b' -> irred b' -> [21:26:56] <antalsz> b = b'. [21:26:56] <antalsz> ``` [21:27:05] <antalsz> but when you check it from _outside_ the section, you see [21:27:05] <antalsz> ``` [21:27:45] <antalsz> and you can see that there’s an extra explicit parameter requiring that `R` is functional [21:28:28] <graydon> ok, so then if I _use_ finseq_unique in Semantics.v, coq is just pulling cstep_functional out of the local environment and supplying it? [21:28:38] <antalsz> You have to do that application yourself [21:28:46] <rhd> https://coq.inria.fr/refman/Reference-Manual004.html#Section [21:28:58] <graydon> I .. just used finseq_unique without providing cstep_functional [21:29:01] <antalsz> Simpler example: [21:29:04] <antalsz> ``` [21:29:04] <antalsz> Section S. [21:29:04] <antalsz> Variable n : nat. [21:29:04] <antalsz> Definition square : nat := n * n. [21:29:04] <antalsz> Check square. [21:29:04] <antalsz> (* square : nat *) [21:29:04] <antalsz> End S. [21:29:04] <antalsz> Check square. [21:29:04] <antalsz> (* square : nat -> nat *) [21:29:04] <antalsz> ``` [21:29:20] <rhd> post your proof script? [21:29:27] <antalsz> Did you fulfill all your obligations? [21:29:36] <rhd> or check what the type of `finseq_unique` is where you used it? [21:30:05] <graydon> @graydon uploaded a file: Untitled https://dsss17.slack.com/files/graydon/F69RH190Q/-.ml [21:30:35] <graydon> (not especially lovely proof, but I just don't quite get where it's conjuring the implicit arg to finseq_unique) [21:30:38] <antalsz> Look at your very first obligation after you apply `finseq_unique` [21:30:57] <antalsz> That’s the functional-relation requirement, and you address it by applying `cstep_functional` :slightly_smiling_face: [21:30:57] <graydon> oh, that's where that came from. [21:31:01] <graydon> hah [21:31:02] <graydon> ok [21:31:12] <graydon> (fell into video-game mode there I guess) [21:31:17] <graydon> thanks! [21:31:18] <antalsz> (And yeah, my proof for that was also ugly) [21:31:20] <antalsz> Sure thing!
1.8.15 TODO Module Advantages / Disadvantages modules
- Advantages
- One advantage to modules over type classes is that you never have to repeat typeclass parameters. Even though you can ameliorate that with a Section, it doesn’t help when you need to open a different section in another file, but other than that, I prefer type classes in nearly every way
- Disadvantages
- This paper http://www.maximedenes.fr/download/refinements.pdf argues against the use of modules in Coq
- The "diamond problem"
- typeclasses allows me to use @ to override a descendent type at a particular use location, whereas with modules I would have to instantiate a whole other set of definitions for each variation
[21:22:31] <jwiegley> One advantage to modules over type classes is that you never have to repeat typeclass parameters. Even though you can ameliorate that with a Section, it doesn’t help when you need to open a different section in another file. [21:22:35] <tsibutpi> this paper http://www.maximedenes.fr/download/refinements.pdf argues against the use of modules in Coq: [21:22:35] <tsibutpi> "The traditional approach to abstraction is to first define an interface specify- [21:22:35] <tsibutpi> ing operators and their properties, then instantiate it with concrete implementa- [21:22:35] <tsibutpi> tions of the operators with proofs that they satisfy the properties. However, this [21:22:35] <tsibutpi> has at least two drawbacks in our context. First, it is not always obvious how [21:22:35] <tsibutpi> to define the correct interface, and it is not clear if a suitable one even exists. [21:22:35] <tsibutpi> Second, having abstract axioms goes against the type-theoretic view of objects [21:22:35] <tsibutpi> with computational content, which means in practice that proof techniques like [21:22:35] <tsibutpi> small scale reflection, as advocated by the [21:22:35] <tsibutpi> SSReflect [21:22:35] <tsibutpi> extension [9], are not [21:22:35] <tsibutpi> applicable." [21:22:42] <jwiegley> but other than that, I prefer type classes in nearly every way [18:59:41] <graydon> I've heard several people disparage the module system in coq as broadly incompatible with several of the needs and idioms of proving theorems; is this less-true when the module has less-logical content and more computational? or less-indexed and more-parametric types? is there some guideline as to when it's worth using, or is the answer just "never if you can avoid it"? [19:03:18] <antalsz> My vote is for “never” – the trouble I ran into, IIRC, was with a module for finite-size words (e.g. 32-bit, 64-bit, 17-bit, …), and that feels fairly computational to me. But I don’t have a principled reason. [19:04:13] <jwiegley> I second @antalsz ‘s vote [19:08:56] <bcpierce> Do you have a principled reason? [19:12:36] <jwiegley> The “diamond problem [19:13:26] <jwiegley> typeclasses allows me to use @ to override a descendent type at a particular use location, whereas with modules I would have to instantiate a whole other set of definitions for each variation [19:15:03] <jwiegley> for example of what the diamond problem even worse than normal is that due to generativity, if B depends on A and C depends on A, and then make a D that depends on B and C, you’ll often get errors about A.foo != A.foo, not realized that B.A.foo and C.A.foo have been generated as different definitions [19:16:16] <jwiegley> whereas with typeclasses where you have defined members rather than typeclasses, you just have an equality witness that must be provided, but it’s fairly clear from the context (after turning on implicits) why the disconnect is happening [19:22:51] <jwiegley> I have one more issue, but let me make an example that will speak louder than my words [19:40:14] <jwiegley> @bcpierce https://gist.github.com/11bf3953995fe37a90f2c4caaeed5d62 [19:40:14] <jwiegley> @jwiegley shared a file: a.rb https://dsss17.slack.com/files/jwiegley/F6ATW6C2C/a.rb [19:41:08] <jwiegley> That code is a problem I recently ran into in real code that I wanted to use (from MIT). Their use of module functors forced me to have to reimplement the subset of their functionality that I needed using type classes, because I was unable to refactor all of my code to use their module type’s interface.
1.8.16 TODO Module parameters / instantiation modules
[22:05:02] <yjsong> Question on Module Type: I want to define something inside Module Type, which solely depends on the interface itself. (does not require instantiation) [22:05:02] <yjsong> For example, with Module Type below,```Module Type Boo. [22:05:02] <yjsong> Parameter t: Type. [22:05:02] <yjsong> Parameter eqb: t -> t -> bool. [22:05:02] <yjsong> Definition eq (a0 a1: t): Prop := if (eqb a0 a1) then True else False. [22:05:02] <yjsong> End Boo. [22:05:02] <yjsong> ```I don't want to define `eq` in each instantiations, but Coq requires me to do this.```Module BooNat <: Boo. [22:05:02] <yjsong> Definition t := nat. [22:05:02] <yjsong> Definition eqb := Nat.eqb. [22:05:02] <yjsong> Definition eq (a0 a1: t): Prop := if (eqb a0 a1) then True else False. (* <----------- *) [22:05:02] <yjsong> End BooNat. [22:05:02] <yjsong> Module BooZ <: Boo. [22:05:02] <yjsong> Definition t := Z. [22:05:02] <yjsong> Definition eqb := Z.eqb. [22:05:02] <yjsong> Definition eq (a0 a1: t): Prop := if (eqb a0 a1) then True else False. (* <----------- *) [22:05:02] <yjsong> End BooZ. [22:05:02] <yjsong> ```How can I solve this? My workaround was to make something like `Module BooFacts (E: Boo)` and instantiate this for each instantiation of `Boo`.. [22:53:51] <jwiegley> @yjsong You can define a module that depends on this module type; people who want to use your module+module type will still need an instantiation of the type. For example, the FMap library requires you to note only import their module, but also provide an instantiation of the DecidableTypeEx module type.
1.8.17 TODO Hint Ordering / Priority auto hints
Can you order things in a hint database? You could do this manually by stratifying hints into different databases, which you then order in a tactic…
A better solution might be to add hint priority values, like so:
[16:22:19] <biv> Is there a way to order things in the hint database ? [16:30:16] <bjones> seems like you could do it manually by stratifying your hints into different databases which you then order in a tactic. [16:32:09] <biv> Yes of course but that looks like more a work around. [16:43:43] <jwiegley> You can give hint priority values…
1.8.18 TODO Reordering subgoals goals
[00:55:44] <vzaliva> Does anybody knows a way to reorder sub-goals? I am applying lemma which generates intermediate sub-goals to satisfy pre-conditions. I would rather prove them right away before proceeding with the rest of the proof. `Focus 2` is the only way I found. [00:56:34] <chobbes> @vzaliva you could always `admit.` and backtrack later. [00:57:33] <dschoepe> ssreflect has some combinators for this, you can write `last first` to handle the last goal first, for instance. Not sure about standard Coq though [00:58:12] <vzaliva> @dschoepe this is exactly what I want! But I do not use ssreflect. Maybe I can write small tactics to reverse the order? [00:58:29] <jwiegley> all:swap 1 2 will swap the position of sub-goals 1 and2 [00:58:35] <jwiegley> I don’t know if there’s a “last” moniker though [00:58:50] <antalsz> If they're sufficiently trivial, you can do `generate_subgoals; [on_first | on_second | | on_fourth]` [00:58:53] <vzaliva> another workaround is: `apply a ; [ idtac; apply xxx; apply yyy]` but this works only if proves are short [00:58:56] <dschoepe> Fwiw, you can simply import ssreflect and only use the parts you want and nothing else though [00:59:03] <jwiegley> @vzaliva Use unshelve before your tactic, i.e.,: `unshelve econstructor.` [00:59:10] <jwiegley> this will present you with the evar goals first [00:59:16] <antalsz> Well, it'll eat your `rewrite` tactic regardless [00:59:25] <andreasloow> do you have a thm to test this on? [00:59:49] <andreasloow> did you test the second one (fold_do’)? [01:00:35] <vzaliva> @jwiegley `unshelve` does not work as they are not shelved in the first place [01:00:53] <jwiegley> which tactic is generating your goals? [01:01:00] <vzaliva> is it something I can try to write in LTAC? sounds like an exercise :slightly_smiling_face: [01:02:16] <jwiegley> @vzaliva There’s also `revgoals` [01:02:28] <vzaliva> @jwiegley 'rewrite' [01:02:35] <jwiegley> ah, I see [01:02:47] <jwiegley> then I would use `all:swap X Y` [01:03:41] <vzaliva> `all:revgoals` is exactly what I need. Thanks @jwiegley ! [01:05:20] <andreasloow> is it idiomatic to swap around subgoals (or reorder them in general)? maybe there are no clear “code standards” for coq proofs… [01:05:27] <andreasloow> looks ugly to me at least :stuck_out_tongue: [01:05:39] <jwiegley> I prefer not to do it if I can avoid it, it makes proofs more brittle [01:06:07] <jwiegley> if you must do it, definitely use bullets or braces also, so you are assured of a fixed number of sub-goals to which it might apply [01:07:14] <andreasloow> yeah, i’m not sure it’s more brittle than relying on the default order, but it’s at least “unnecessary code”, in the sense that it’s not needed [01:07:20] <andreasloow> one then wonders why it’s there [01:07:40] <andreasloow> (someone reading the proof later, that is) [01:08:35] <vzaliva> if you view your proof as a script (sequence of steps) it is confusing to left with bunch of subgoals at the end collected from all the steps. I would like to complete each step along with it's sub-goals before proceeding to the next. [01:09:13] <jwiegley> braces can certainly help with that [01:09:14] <andreasloow> what’s the context? [01:09:29] <jwiegley> { rewrite foo. - subgoal1 - subgoal2 - subgoal3 } [01:09:43] <jwiegley> you can’t “move on” until every subgoal is discharged [01:10:39] <denisredozubov> yes [01:10:48] <andreasloow> looks better if it works the way i think it works :slightly_smiling_face: [01:10:50] <vzaliva> It is also strange now goals are numbered during rewrite. I have only one goal first, and do a rewrite. I would expect it to rewrite my current goal and add (in my case) 2-sub goals. Instead it creates 2 sub-goals at the same level.
1.8.19 Destruct notations notation
You can do destruct on notations like this:
destruct "[=]".
1.8.20 pattern term
tactics
https://coq.inria.fr/distrib/current/refman/proof-engine/tactics.html#coq:tacn.pattern
pattern x
will abstract all occurrences of x
, so for instance
it will change x + 1
into (fun v => v + 1) x
. This can be
useful for some automation and applications, which are expecting
function applications.
1.8.21 TODO Custom induction principles induction
[13:39:08] <nomeata> How do I use `induction … using my_custom_ind with …` if `my_custom_ind` is a custom induction lemma with additional premises on the induction variable, e.g.```my_custom_ind : forall m P, P m -> (forall n, P (S n) -> P n) -> forall n, n <= m -> P n [13:39:08] <nomeata> ```Do I have to move the `n <= m` somewhere else in `my_custom_ind`? [13:40:26] <jwiegley> Can you show some representative code? [13:41:02] <jwiegley> you could also apply the induction premise directly, rather than using “induction” [13:41:35] <jwiegley> you may need to use `pattern x` so `apply` can infer `P` easily [13:44:46] <nomeata> The representative code is pretty large (8 cases)… I’ll build an example from `my_custom_ind`… [13:45:26] <antalsz> @jwiegley What does `pattern x` do? [13:45:48] <jwiegley> it changes `x + 1` into `(fun v => v + 1) x` [13:46:10] <jwiegley> abstracting all occurrences of `x` [13:48:34] <nomeata> Can I make this somehow work with the `induction` tactic:```Axiom my_custom_ind : forall m P, P m -> (forall n, P (S n) -> P n) -> forall n, n <= m -> P n. [13:48:34] <nomeata> Lemma foo: [13:48:34] <nomeata> forall a b c, [13:48:34] <nomeata> b < c -> a <= b -> a < c. [13:48:34] <nomeata> Proof. [13:48:34] <nomeata> intros. [13:48:34] <nomeata> generalize dependent a. [13:48:34] <nomeata> induction a using my_custom_ind. [13:48:34] <nomeata> ```(The premises of `my_custom_ind` may be rearranged if it makes `induction` happy.) [13:52:38] <jwiegley> I think part of the problem is that `m` is not mentioned in `P n`, so it cannot be inferred (not even with `einduction` it seems). [13:52:42] <jwiegley> However, this works: `eapply my_custom_ind; eauto; intros; omega.` [13:54:33] <biv> `induction a` is equivalent to ` apply nat_ind with (n := a) ; intros.` [13:54:48] <nomeata> Shoudln’t `induction a using my_custom_ind with (m := b).` fix this problem about infering `m`? [13:55:25] <jwiegley> the Axiom doesn’t name its arguments [13:55:31] <jwiegley> let me try something with Arguments… [13:56:44] <nomeata> (Maybe induction with custom induction schemes with additional premises is simply not supported in Coq?) [13:56:45] <jwiegley> no, I can’t get it to recognize the pattern [13:57:22] <jwiegley> I think I’ve used additional arguments before, but they appeared in the final type [13:57:59] <nomeata> Interestingly, in my real example the error message is not `Error: Cannot recognize the conclusion of an induction scheme.` but rather `Error: Not the right number of induction arguments (expected 1 parameter and 2 arguments).` [13:59:18] <nomeata> Maybe I should step back one step and ask “How do I define an induction principle (usable with `induction`) that proofs a proposition not for all values of a type, but only those that satisfy one or more predicates.” [14:03:07] <jwiegley> can you induct on `a <= b` instead? [14:03:17] <jwiegley> that solves your sample proof, but I don’t know about your real proof [14:03:52] <jwiegley> in other words, if you have an inductive proposition encoding your property, then induction on that can be the same as induction on a var+evidence of the property at each step [14:04:09] <nomeata> No no, this is just an example for an arbitrary side condition. [14:05:04] <nomeata> (I guess I’ll continue with careful use of `apply`. Maybe this is simply not supported.) [14:08:08] <biv> @nomeata you should not rely on the naming of the hypothesis by induction. this is not robust. :confused: [14:09:29] <nomeata> Ok, I’ll rely on the naming of the hypothesis by `apply` then :wink: [14:10:03] <nomeata> `induction` also seems to reorder the hypotheses more sensible. [14:10:49] <biv> you can also do it directly in `induction n as [| n IHn ]` or if with more hypothesis `induction h as [IHh | IHh | n IHhn]` ... :slightly_smiling_face: [14:11:24] <nomeata> Not fun with 8 cases, each of which have 1 to 6 parameters and hypotheses [14:11:51] <biv> `match goal with ... end` [14:34:23] <nomeata> In my current project, I solved the fixedpoint problem by, in `iterate`, replace `F x` with `lub x (F x)`. Then I can move the preconditions on `F` to the lemmas that show that I really calculated the fixpoint.
1.8.22 TODO Destructing multiple existential variables destruct
[18:04:07] <chobbes> Is there a way to destruct all existentially qualified variables in a hypothesis? [18:04:32] <chobbes> E.g., `exists x y, P x y`. I want to get the particular x and y. [18:05:28] <chobbes> Oh wait, I bet patterns work. [18:05:56] <chobbes> Success! [18:06:09] <chobbes> `destruct H as [x [y H]].` [18:06:13] <curtis> I've been destructing them one at a time. paste? ah thanks [18:08:45] <jwiegley> @chobbes Also: [18:08:45] <jwiegley> ```Ltac destruct_ex := repeat match goal with [18:08:45] <jwiegley> | [ H : exists _, _ |- _ ] => destruct H [18:08:45] <jwiegley> end. [18:08:45] <jwiegley> ``` [18:08:45] <jwiegley> The works because `exists x y, z` is really `exists x, exists y, z`. [18:59:29] <jannis> @chobbes @jwiegley Also: `repeat destruct H as [? H]`.
1.8.23 Ltac naming ltac
In Ltac you can give something an automatically generated fresh
name with ?
in an "intros list". An example of this is:
destruct H as [? Hblah]
Using ?
in this way is similar to using fresh
to generate a
new name, like so:
let H' := fresh "H" in destruct H as [H' Hblah]
?
may try to be smart about naming, like giving names starting with n
to nat
types.
1.8.24 TODO Instance / Program Instance instance program_instance
[19:11:30] <denisredozubov> btw I totally forgot what’s difference between `Program Instance` and `Instance` [19:11:39] <jwiegley> the Program environment has a lot more magic [19:11:44] <denisredozubov> Someone asked that today, but I guess I’ve drifted off. [19:11:49] <jwiegley> and you prove the generated goals with Next Obligation rather than Proof [19:12:02] <jwiegley> Program Instance will infer a lot of things that Instance won’t [19:12:10] <jwiegley> btw, I use Program Instance almost exclusively; I love it [19:12:52] <jwiegley> you can change which tactic it uses to auto-solve goals with Local Obligation Tactic := …, which can be super handy
1.8.25 Decidable equality and conditionals dec_eq
eq_dec : forall x y : atom, {x = y} + {x <> y}
And ==
is notation for eq_dec a b
.
Now suppose you end up with a goal like:
u = (if x == x then u else blah)
Since x == x
is just notation for eq_dec x x
, you can do
destruct (x == x)
which will split the goal into two, one with the hypothesis x = x
, and the other with the hypothesis x <> x
.
In the first case, where x = x
the goal should be solvable (auto
should be
sufficient in this specific instance).
The second case, where x <> x
, is solvable by contradiction
.
Using destruct (_ == _)
can be a bit annoying, since you end up
splitting the goal, only to dismiss one with contradiction
, so
it may be more convenient to rewrite using a theorem like the
following:
Theorem eq_dec_refl {A : Type} `{EqDec_eq A} (x : A) : eq_dec x x = left eq_refl. Proof. destruct (eq_dec x x); [|contradiction]. f_equal; apply (Eqdep_dec.UIP_dec eq_dec). Qed.
https://github.com/plclub/metalib/pull/10/files
(left
is the first constructor of the sumbool
type, so it is the equivalent of "true" for the if expression)
1.8.26 UIPDec dec_eq
EqDep_dec.UIP_dec
can be handy for avoiding the JMeq_eq
axiom when you have decidability.
1.8.27 TODO Generators qc
[15:08:16] <vi> wonders if we can write generators for dependent products, e.g. \Sigma{l}{sorted}. [15:10:06] <jwiegley> sure: generate sorted lists, and then use the fact that sort produces evidence for sorted [15:10:22] <vi> I guess that works wherever we have a function on the order of l’s carrier with l <= f(l). [15:10:27] <vi> (The generator).
1.8.28 TODO Extrinsic / intrinsic verification
[16:22:03] <joomy> Extrinsic verification is nice for productivity, sure. My complaint about it is that intrinsic verification often plays much nicer with termination checking. Say you are pattern matching on a list, and you need to make recursive calls with an arbitrary strict suffix of a list. Termination checker would not be able to detect that. But if you have an argument of a type that describes the suffix relation, you can convince the termination checker to pick it up. Otherwise you would probably have to resort to the fuel idiom and show that the fuel is enough etc.
1.8.29 Minifier tools
Jason Gross has a “minifier” for Coq programs that reveal bugs in the compiler, in order to produce better bug reports for the Coq team:
https://github.com/JasonGross/coq-tools/blob/master/find-bug.py .
It’s quite easy to use, provided you can reduce any external dependencies.
1.8.30 TODO Module Functors modules
[18:41:03] <ins> Say I have a module type: [18:41:03] <ins> ``` [18:41:03] <ins> Module Type EquivSig. [18:41:03] <ins> Parameter t : Type. [18:41:03] <ins> Parameter eq : t -> t -> Prop. [18:41:03] <ins> 5 Axiom eq_refl : forall x, eq x x. [18:41:03] <ins> 6 Axiom eq_sym : forall x y, eq x y -> eq y x. [18:41:03] <ins> 7 Axiom eq_trans : forall x y z, eq x y -> eq y z -> eq x z. [18:41:03] <ins> 8 End EquivSig. [18:41:06] <ins> Woops [18:43:18] <ins> And I'd like to have a second signature that depends on this one, something like: [18:43:18] <ins> ```Require Import Equiv. [18:43:18] <ins> Module Type Poset. [18:43:18] <ins> Parameter EQ : Equiv. [18:43:18] <ins> Parameter t : Type. [18:43:18] <ins> Parameter order : t -> t -> Prop. [18:43:18] <ins> Axiom order_refl : forall x y, EQ.eq x y -> order x y. [18:43:18] <ins> Axiom order_antisym : forall x y, order x y -> order y x -> EQ.eq x y. [18:43:18] <ins> Axiom order_trans : forall x y z, order x y -> order y z -> order x z. [18:43:18] <ins> End Poset. [18:43:18] <ins> ``` [18:43:40] <ins> Is there a way to do this? Or do I have to inline the signature for Equiv in the signatuer for Poset? [18:44:39] <ins> Of course you'd also need to specify somehow that EQ.t = t. [18:50:20] <antalsz> @ins This is what “functors” (not like in Haskell) are for: you have to specify that `Poset` takes another _module_ as a parameter, which satisfies the module type `Equiv`. [18:50:22] <antalsz> ``` [18:50:34] <antalsz> ``` [18:50:34] <antalsz> Module Type Poset (EQ : Equiv) <: Equiv. [18:50:34] <antalsz> Include EQ. [18:50:34] <antalsz> [18:50:34] <antalsz> Parameter order : EQ.t -> EQ.t -> Prop. [18:50:34] <antalsz> Axiom order_refl : forall x y, EQ.eq x y -> order x y. [18:50:34] <antalsz> Axiom order_antisym : forall x y, order x y -> order y x -> EQ.eq x y. [18:50:34] <antalsz> Axiom order_trans : forall x y z, order x y -> order y z -> order x z. [18:50:34] <antalsz> End Poset. [18:50:34] <antalsz> ``` [18:50:56] <ins> Ah, you can have functor signatures [18:50:59] <ins> I didn't knw taht [18:51:01] <ins> know* [18:51:22] <ins> Mm this isn't quite what I want I don't think? [18:51:25] <ins> Or maybe it is. [18:51:28] <antalsz> Actually, you can drop all the `EQ.` parts – edited [18:51:51] <ins> Nevermind, I think this is what I want [18:52:01] <ins> thanks! [18:52:05] <antalsz> No problem! [18:56:44] <ins> Isn't `EQ` already annotated as being type `Equiv`? [18:56:59] <robblanco> @ins Do you mean functors in OCaml? Sure, you can have those. Maybe I'm missing some of the context. [18:57:03] <lemonidas> It's saying that `Poset` is also `Equiv` I think [18:57:10] <ins> Functor signatures [18:58:01] <ins> Modules can satisfy multiple signatures? [18:58:13] <ins> (e.g. have multiple types?) [18:59:19] <antalsz> @ins @lemonidas is right, it says that `Poset` depends on an `Equiv` and is also an `Equiv` [18:59:34] <antalsz> Without the `Import EQ.` line, you’d have to drop the `<: Equiv` (and add back the `EQ.`)
1.8.31 TODO Sigma types sigma
[19:28:12] <npe> Can anyone explain “proj2_sig”? [19:28:22] <jwiegley> it’s the second member of a propositional sigma [19:28:57] <jwiegley> forall x : { a : T | P T }, (proj2_sig x : P (proj1_sig x)) [19:29:24] <npe> I’ve found the definitions, but I don’t have context to understand what it’s actually doing. [19:29:57] <npe> What is a propositional sigma? RTFM with a pointer to a paper/manual would be a great answer. [19:30:16] <jwiegley> it’s a datum along with a witness to the truth of some proposition for that datum [19:30:27] <jwiegley> x, plus evidence that P x [19:30:50] <jwiegley> proj1_sig gets you the value, proj2_sig gets you the witness to the proposition [19:31:04] <jwiegley> (however, note that these only work in a propositional context) [19:31:58] <npe> I think I vaguely get it (from the context).
1.8.32 TODO ..
problems in PG bugs
[01:44:30] <chobbes> Does `..` happen to mean anything in Coq? I keep getting ProofGeneral stuck on this. [01:45:02] <antalsz> @chobbes Only in some contexts, because Coq is like that :stuck_out_tongue: [01:45:22] <antalsz> But what’s probably happening is that it’s processing up to the first `.`, then getting confused when it tries to process the string `.` as a complete command [01:45:22] <chobbes> @antalsz What do you mean? [01:45:36] <chobbes> Yeah. [01:45:41] <chobbes> This seems to be what happens. [01:45:49] <chobbes> Like if you end a tactic with `..` [01:45:52] <chobbes> And try to run it. [01:45:58] <chobbes> It just gets stuck forever. [01:46:15] <chobbes> But it's not really hogging CPU or anything. I think it's just sitting there confused...? [01:46:35] <antalsz> @chobbes `Notation "'exists' x .. y , p" := ex (fun y => .. (ex (fun y => p)) ..)` [01:46:45] <antalsz> `..` is used for recursive/infinite notations like that [01:47:11] <chobbes> Ahhhhh. [01:47:26] <chobbes> shakes fist. [01:47:32] <antalsz> And there’s nothing stopping you from defining `Notation "x '..' y" := (x,y) (at level 10).` [01:48:01] <chobbes> Sure, but I feel like this is a bug still. [01:48:07] <antalsz> But those aren’t why it’s getting stuck – I’m fairly sure it’s just PG getting confused [01:49:04] <antalsz> OK, so I tried something [01:49:13] <antalsz> ```% rlwrap coqtop [01:49:13] <antalsz> Welcome to Coq 8.6 (July 2017) [01:49:13] <antalsz> Coq < Goal True. [01:49:13] <antalsz> 1 subgoal [01:49:13] <antalsz> [01:49:13] <antalsz> ============================ [01:49:13] <antalsz> True [01:49:13] <antalsz> Unnamed_thm < idtac.. [01:49:13] <antalsz> Unnamed_thm < idtac. [01:49:13] <antalsz> Toplevel input, characters 5-7: [01:49:13] <antalsz> > idtac.. [01:49:13] <antalsz> > ^^ [01:49:13] <antalsz> Syntax error: [tactic:ltac_use_default] expected after [tactic:tactic] (in [vernac:tactic_command]). [01:49:13] <antalsz> Unnamed_thm < [01:49:13] <antalsz> ``` [01:49:16] <chobbes> Oh no, something! [01:49:45] <antalsz> So it looks like what’s happening with the `..` is that there’s a syntax error but Coq can’t quite tell yet? [01:50:02] <chobbes> Oh god, is coqtop one of those awful programs that can't handle user input properly? :stuck_out_tongue: (re: rlwrap) [01:50:04] <antalsz> And PG gets confused because it didn’t see the response it expected [01:50:28] <antalsz> Alas, yes:```% coqtop [01:50:29] <antalsz> Welcome to Coq 8.6 (July 2017) [01:50:29] <antalsz> Coq < Goal True. [01:50:29] <antalsz> 1 subgoal [01:50:29] <antalsz> [01:50:29] <antalsz> ============================ [01:50:29] <antalsz> True [01:50:29] <antalsz> Unnamed_thm < ^[[A [01:50:29] <antalsz> ``` [01:51:28] <chobbes> I wrote my own rlwrap once because I didn't know rlwrap existed, lol. [01:51:37] <chobbes> Note to all: Google your problem first. [01:52:09] <antalsz> Anyway, my advice for when PG gets blocked like that is `C-c C-u`, aka `proof-undo-last-successful-command` [01:52:32] <pmetzger> BTW, is Proof General eventually going to support the parallelism stuff in CoqIDE? [01:52:32] <chobbes> @antalsz it just says that the proof process is busy! [01:52:47] <pmetzger> (Or is this an #emacs question? :) [01:53:08] <antalsz> And if that fails, `C-c C-x`, aka `proof-shell-exit`, followed by `C-c <C-return>`, aka `proof-goto-point` [01:53:28] <antalsz> @chobbes Oh, right [01:53:31] <chobbes> @antalsz ah yes, thank you. I always forget that one, and was searching for "quit" which doesn't exist. [01:53:58] <antalsz> I actually recommend `C-c C-c` followed by `C-c C-u`, aka `proof-interrupt-process` followed by `proof-undo-last-successful-command` [01:54:06] <chobbes> `C-c C-x` is like... mighty close to `C-x C-c` [01:54:42] <antalsz> Luckily I have all a nicely paranoid quit option turned on [01:54:47] <chobbes> Aha! That worked! [01:54:48] <antalsz> I mean, who exits Emacs? :stuck_out_tongue: [01:55:13] <chobbes> `:q!` [01:55:23] <antalsz> I agree that there’s a bug _somewhere_ in all of this, but I dunno if it’s in PG, Coq, both, or what [01:55:36] <antalsz> Luckily “no, stop that, go back” usually seems to suffice [01:55:43] <chobbes> Yeah :slightly_smiling_face:. [01:55:53] <chobbes> Good to know how to recover. [01:56:03] <chobbes> `pkill coqtop` felt slightly wrong.
1.8.33 Replacing with A:=B set
Suppose using set
you end up with A := B
in the context, and you want to rewrite using this.
unfold A
,subst A
, orreplace A with B by reflexivity
should rewriteA
withB
in the goal.fold A
should rewriteB
withA
in the goal.
1.8.34 Coqtop bugs
1.8.35 ProofGeneral saving contents of buffers pg
Useful keybindings in ProofGeneral: C-c C-a r
and C-c C-a g
,
for persisting the contents of the goal and response buffer in
another, special buffer, which accumulate each such output.
1.8.36 ProofGeneral look up information about identifier pg
C-c C-i
will run check on the identifier at point.
1.8.37 In Depth Semicolons
The impression is that the semicolon operator, bar; foo
, will
run foo
on all goals created by bar
.
gfail
fails even when there are no goals, so foo; gfail
will
actually fail, even if foo
solves all goals, whereas foo; fail
will succeeds.
Running tactics after a semicolon when there are no remaining
goals makes a lot of sense, though. It's reasonable to want to
print after running a tactic, for instance admit; idtac "hello!"
1.8.38 TODO InvertN tactics
[14:27:15] <lemonidas> For whoever interested, I just wrote a Coq plugin that automates "invertn" [14:27:16] <lemonidas> https://github.com/lemonidas/invertn_tactic [15:04:41] <jwiegley> @lemonidas That’s great! I was unable to do it with native Ltac, due to incompatibility between Coq terms and OCaml integers: [15:04:41] <jwiegley> ```Ltac invert_internal n H := [15:04:41] <jwiegley> lazymatch n with [15:04:41] <jwiegley> | 0 => inversion H; clear H; subst [15:04:41] <jwiegley> | S ?n' => invert_internal n' H; let g := numgoals in guard g < n [15:04:41] <jwiegley> end. [15:04:41] <jwiegley> Tactic Notation "invert" integer(n) constr(H) := invert_internal n H. [15:04:41] <jwiegley> ``` [16:09:35] <dschoepe> ```Ltac invert_internal n H := [16:09:35] <dschoepe> inversion H; subst; clear H; [16:09:35] <dschoepe> let g := numgoals [16:09:35] <dschoepe> in guard g <= n. [16:09:35] <dschoepe> ``` [16:12:53] <jwiegley> For efficiency, move the subset and clear after the guard? [16:13:04] <bcpierce> Oh yes, I missed some semicolons when I did the change. It does work now. [16:13:05] <dschoepe> good point [16:13:07] <bcpierce> Thanks!! [16:13:40] <jwiegley> Just: [16:13:40] <jwiegley> ```Tactic Notation "invert" integer(n) constr(H) := [16:13:40] <jwiegley> inversion H; let g := numgoals in guard g <= n; clear H; subst. [16:13:40] <jwiegley> ```
1.8.39 TODO coq-compile-before-require pg
[15:07:10] <denisredozubov> btw after following the instructions from `tutorial/Tutorial.md` and skimming down the tutorial I’ve tried compiling `CAL/stack/Counter.v` and each `Require` statement takes an eternity to evaluate [15:07:25] <denisredozubov> it looks like it compiles `compcert` yet again [15:08:17] <dschoepe> This may be the case if you turned on `coq-compile-before-require` perhaps? [15:09:52] <denisredozubov> it is [15:10:10] <denisredozubov> I don’t have a general sense when I want to have this variable set to `t` [15:10:44] <jwiegley> @denisredozubov I always use it, FWIW [15:11:11] <heiko> @dschoepe As far as I know, compile before require only recompiles if necessary, hence that should not be a bottleneck. [15:11:39] <pmetzger> if you load a second time does it do it yet again? [15:11:49] <pmetzger> or does it remember the last set of compiles? [15:11:52] <denisredozubov> There is a different instance of compcert in a repo, I believe [15:11:53] <jwiegley> it saves the .vo [15:12:11] <pmetzger> I was asking @denisredozubov in his particular case. [15:12:22] <denisredozubov> i wonder if it makes sense to run `make` and package all the `.vo` files with nix [15:12:23] <heiko> @pmetzger It smartly recompiles, if you changed the file being imported [15:12:49] <denisredozubov> @pmetzger It haven’t finished doing this [15:13:01] <pmetzger> you built compcert before now? [15:13:34] <denisredozubov> yes, I’ve used nix for that [15:13:55] <denisredozubov> https://github.com/CertiKOS/compcert I see this one in `CAL` folder [15:14:27] <denisredozubov> which is different from the compcert that was used last week
1.8.40 Ltac Debugging in Proof General ltac debugging pg
There is no integration of the Ltac debugger in proof general, but
you can switch to the \*coq\*
buffer to use the debugger
directly.
1.8.41 Inversion subst warning ltac tactics best_practices
inversion H; subst; clear H
is a common pattern, but sometimes
does not lead to nice results since the subst
can cause large
substitutions, leading to a really complicated context, or it can
often rewrite hypothesis that you want to keep intact.
1.8.42 Ltac bug fixing ltac
Adam Chlipala points out:
Let me just point out that "fixing bugs in the Ltac semantics" often forces significant amounts of code to be rewritten after extensive debugging.
1.8.43 Redefining Ltac ltac
::=
can be used to redefine existing Ltac definitions.
1.8.44 TODO Cut tactics
[23:56:41] <graydon> for whoever was asking earlier today about "cut" in ltac: there appears to be a _hint_ form that automatically does a cut in the prolog sense of pruning the search tree. it uses (hold on to your hat) a _regular expression over the path of hint-identifiers_ in the tree, to decide where to cut. it also only works currently in the typeclass proof search, not general proof search. but maybe they'll extend it someday. [23:58:54] <graydon> oh wait I misunderstood; typeclass eauto is maybe generally-applicable? [00:03:42] <graydon> yeah, it looks like "typeclasses eauto with core" will run the new proof engine on the core auto database, making it usable in contexts where you'd normally use auto. and then you can, yeah (guh) prune the tree with Hint Cut <regexp>.
1.8.45 Refine vs Exact tactics
There are two similar tactics built into Coq, refine
and
exact
. Both let the user supply a Gallina term which can satisfy
a goal (if the term has a type that matches).
exact
has to give a term which is complete and exactly matches
the goal.
With refine
the user can put holes in places which create
subgoals. For instance you could destruct something like:
refine (match something with | false => _ | true => _ end).
Which would give you a subgoal for each branch.
1.8.46 TODO Unshelve tacticals
[03:54:26] <vikraman> I think `unshelve eapply` just works a little harder to introduce evars, I've had cases where refine wouldn't allow me to leave holes in certain places. [00:47:13] <denisredozubov> > `All the remaining goals are on the shelf.` [00:47:19] <denisredozubov> what does that mean? [00:52:55] <jwiegley> you need to use `Unshelve` to see them [00:53:15] <jwiegley> these are generated goals, typically to resolve evars, which are not visible at first [00:57:05] <denisredozubov> how does this interact with `unshelve <tactic>` that was shown today? Is it unshelve the first shelved goal and then apply the tactic? [01:36:25] <yjsong> @denisredozubov I think `Unshelve` is top-level keyword (like Qed.) and `unshelve` is tactical. [01:37:41] <yjsong> IIUC, `Unshelve` will put all shelved goals into visible state, and `unshelve` does this for only the shelved goals made by next tactic. [01:38:37] <yjsong> Actually I cannot find documentation on `unshelve` but I was able to find this: https://github.com/ProofGeneral/PG/issues/30#issuecomment-173974922 [01:56:11] <jwiegley> unshelve eauto does not send the evar goals to the shelf [01:56:25] <jwiegley> unshelve is undocumented, but very useful
1.8.47 Congruence tactic
https://coq.inria.fr/distrib/current/refman/proof-engine/tactics.html#coq:tacn.congruence
Congruence can usually solve goals where you only have to do rewriting.
1.8.48 ||
and +
ltac tacticals
||
and +
are somewhat similar ways of combining tactics.
t1 || t2
runs t2
if t1
"doesn't do anything", which means
that it does not change the proof state. So, for example auto ||
fail "auto failed"
would fail iff auto
did not do anything.
fail || t ≡ t
and intros X || t ≡ intros X
as you might
expect, but idtac || t ≡ t
fail + t ≡ t
and intros X + t ≡ intros X
, as well as idtac +
t ≡ idtac
.
first [t1 | t2 | … | tN]
is like t1 + t2 + … + tN
, except for
a minor detail with failure levels
1.8.49 Progress tactics
To know what it means for a tactic to make progress, it might be illustrative to look at the progress tactic:
https://coq.inria.fr/distrib/current/refman/proof-engine/ltac.html#coq:tacn.progress
1.8.50 Extraction extraction
Coq extraction takes Gallina to a languaged called mini-ml, which is then further transformed to other languages.
Main bit of the ocaml extraction (this isn't including support code for number representations and such):
https://github.com/coq/coq/blob/master/plugins/extraction/ocaml.ml
1.8.51 Undocumented tactics as of 8.5 tactics documentation
autoapply
autounfold_one
debug auto
debug eauto
debug trivial
dependent generalize_eqs
dependent generalize_eqs_vars
destauto
destruct_with_eqn
dfs eauto
generalize_eqs
generalize_eqs_vars
gintuition
goal
guard
head_of_constr
hget_evar
hresolve_core
info
info_auto
info_eauto
infoH
info_trivial
new auto
now
progress_evars
prolog
rec
rewrite_all
rewrite_db
setoid_etransitivity
simple subst
soft functional induction
specialize_eqs
substitute
unshelve
etransitivity
zify
1.8.52 Is there a way to turn off notations when printing? notations
Sometimes notations can be confusing and get in the way, if you want to disable notations when Coq is printing out information you can try:
Unset Printing Notations.
So, for instance:
Unset Printing Notations. Theorem foo : forall (a b : nat), a <= b -> a < b.
will print the goal as:
forall (a b : nat) (_ : le a b), lt a b
instead of:
forall a b : nat, a <= b -> a < b
1.8.53 TODO Functional induction tactics induction
[15:39:19] <dschoepe> Just in case people don't know about this feature, but Coq can auto-generate induction principles following the "shape" of a function. Then the previous lemma can be proven like this as well: [15:39:19] <dschoepe> ```Functional Scheme ins_ind := Induction for ins Sort Prop. [15:39:19] <dschoepe> Functional Scheme balance_ind := Induction for balance Sort Prop. [15:39:19] <dschoepe> Lemma ins_not_E': forall x vx s, ins x vx s <> E. [15:39:19] <dschoepe> Proof. [15:39:19] <dschoepe> unfold not. [15:39:19] <dschoepe> intros x vx s He. [15:39:19] <dschoepe> functional induction (ins x vx s); eauto; try discriminate; [15:39:19] <dschoepe> match goal with [15:39:19] <dschoepe> | [ H : balance ?a ?b ?c ?d ?e = _ |- _ ] => [15:39:19] <dschoepe> functional induction (balance a b c d e); [15:39:19] <dschoepe> try discriminate; eauto [15:39:19] <dschoepe> end. [15:39:19] <dschoepe> Qed. [15:39:19] <dschoepe> ``` [15:39:19] <dschoepe> Not shorter than the automation from the lecture but it requires less thinking, arguably.
1.8.54 match reverse ltac
match reverse goal with
matches hypothesis in the reverse order
from a regular match.
Ltac test_ltac := match goal with | H : _ |- _ => idtac H end. Ltac test_ltac_rev := match reverse goal with | H : _ |- _ => idtac H end. Theorem foo : forall (A B : Prop), True. Proof. intros A B. test_ltac. test_ltac_rev. Qed.
This will print B
when test_ltac
is run, and A
when
test_ltac_rev
is run.
1.8.55 Notations for repeated patterns (like lists) notation
..
in notations lets you define repeated patterns that get expanded.
1.8.56 Proof with tactics
You can use Proof with <tactic>
where <tactic>
is replaced by
some tactic to make proofs a bit shorter.
Proof with t
will cause t1...
to behave like t1; t
automatically. If you find yourself using t
a lot in a proof,
using Proof with t
can make things shorter.
Here's a small example:
Theorem easy_theorem: forall A (a : A), a = a. Proof with auto. intros A a... Qed.