I was wondering how do I get turnstile to work in Isabelle 2017. I new to the program and have been able to work some thereoms but I can't figure out how to get the turnstile symbol to work. Do I have change imports or is there something else I have to do?
Thanks.
Okay, so it seems like you want to define some custom syntax involving the turnstile symbol.
This is described in Sections 8.2 and 8.3 of the Isabelle/Isar reference manual (and some more advanced stuff in Sections 8.5.2 and 8.5.3). You can do a lot of fancy custom syntax with Isabelle: the list syntax [1, 2, 3] for Cons 1 (Cons 2 (Cons 3 Nil)), for example, is defined entirely in ‘user space’, as is the list comprehension syntax [x + y. x ← xs, y ← ys, x ≠ y]. These are pretty complicated.
However, in most cases, you only need a very small fragment of all that power: As outline in Section 8.2 of isar-ref, you can annotate syntax directly to constants as you define them (e.g. with definition, primrec, fun, datatype) by either using something like infixl, infixr, or binder, or by directly providing a mixfix syntax specification. The tricky part here is often defining the precedences so that they don't clash with other stuff.
If you get this wrong, you will get warnings (not upon defining the syntax, but upon using it) telling you that there are ambiguous parse trees and that you should perhaps try to disambiguate your syntax by providing better mixfix priorities.
For examples of how this looks in practice you can look, well, basically at any Isabelle syntax you already know by going to where it is defined and looking at the mixfix specification.
One place that comes to my mind is the ~~/src/HOL/IMP directory, in particular the files Hoare.thy and Types.thy. They define some custom syntax, some of which even includes the turnstile symbol.
Related
I know there is macro-function, explained here, which allows you to check, but is it also possible in simply reading lisp source to sometimes infer of what you're looking at "that must be a macro"? (assuming of course you have never seen the function/macro before).
I'm fairly sure the answer is yes, but as this seems so fundamental, I thought worth asking, especially because any nuances on this may be valuable & interesting to know about.
In Paul Graham's ANSI Common Lisp, p70, he is describing how to use defstruct.
When I see (defstruct point x y), were I to know absolutely nothing about what defstruct was, this could just as well be a function.
But when I see
(defstruct polemic
(subject "foo")
(effect "bar"))
I know that must be a macro because (let's assume), I also know that subject and effect are undefined functions. (I know that because they error with undefined function when called 'at the top level'(?)) (if that's the right term).
If the two list arguments to defstruct above were quoted, it would not be so simple. Because they're not quoted, it must be a macro.
Is it as simple as that?
I've changed the field names slightly from those used on the book to make this question clearer.
Finally, Graham writes:
"We can specify default values for structure fields by enclosing the field name and a default expression in a list in the original definition"
What I'm noticing is that that's true but it is not a (quoted) list. Would any readers of this post have phrased the above sentence at all differently (given that macros haven't been introduced in the book yet (though I have a basic awareness of what they are)).
My feeling is it's not a "data list" those default expressions are enclosed in. (apologies for bad terminology) - seeking how rightly to conceptualise here.
In general, you're right: if there's some nesting inside the call and you are sure that the car's of the nested lists aren't functions - it's a macro.
Also, almost always, def-something and with-something are macros.
But there's no guarantee. The question is, what are you trying to accomplish? Some code walking/transformation or external processing (like in an editor). For the latter, you should keep in mind that full control is possible only if you perform code evaluation, although heuristics (like in Emacs) can take you pretty far. Or you just want to develop your intuition for faster code reading...
There is a set of conventions that identify quite cleary what forms are supposed to be macros, simply by mimicking the syntax of existing macros or special operators of CL.
For example, the following is a mix of various imaginary macros, but even without knowing their definition, the code shouldn't be too hard to figure out:
(defun/typed example ((id (integer 0 10)))
(with-connection (connection (connect id))
(do-events (event connection)
(event-case event
(:quit (&optional code) (return code))))))
The usual advice about macros is to avoid them if possible, so if you spot something that doesn't make sense as a lisp expression, it probably is, or is enclosed in, a macro.
(defstruct point x y)
[...] were I to know absolutely nothing about what defstruct was, this could just as well be a function.
There are various hints that this is not a function. First of all, the name starts with def. Then, if defstruct was a function, then point, x and y would all be evaluated before calling the function, and that means the code would be relying on global variables, even though they are not wearing earmuffs (e.g. *point*, *x*, *y*), and you probably won't find any definition for them in the preceding forms (or later in the same compilation unit). Also, if it was a function, the result would be discarded directly since it is not used (this is a toplevel form). That only indicates the probable presence of side-effects, but still, this would be unusual.
A top-level function with side-effects would look like this instead, with quoted data:
(register-struct 'point '(x y))
Finally, there are cases where you cannot easily guess if you are using a macro or a function:
(my-get object :slot)
This could be a function call, or you could have a macro that turns the above to (aref object 0) (assuming :slot is the zeroth slot in object, because all your objects are assumed to be of a certain custom type backed by a vector). You could also have compiler macros. In case of doubt, try to macroexpand it and look at the documentation.
you've been spectacularly helpful to me so far, I hope you can help me get my mind around this one. I am building a project that does computations with complex matrices. I have been using mikera/core.matrix.complex, which uses mikera/core.matrix for matrix stuff, and complex.core for defining complex numbers in clojure.
I want to be able to do any and all arithmetic, including using irrational numbers like e (def e (Math/E)) and pi (def pi (Math/PI)), and including matrix math that may or may not be complex. The problem comes when I mix functions from different libraries.
Right now my namespace looks like this:
(ns qgame.utils.math
(:require
[clojure.walk :as w :refer [postwalk
prewalk]]
[clojure.core.matrix :as mat]
[clojure.core.matrix.complex :as compl]
[incanter.core :as ic]
[complex.core :as c :refer [+ - / *]]))
If I do (mat/mmul matrix1 matrix2), then everything is treated as a regular number, and using complex numbers messes it up. I get a lot of ClassCastException org.apache.commons.math3.complex.Complex cannot be cast to java.lang.Number. If I just require core.matrix.complex without requiring core.matrix, then none of the matrix functions work.
The same goes for stuff like (+ 3 4). If I directly (use 'complex.core) in a repl, then that will evaluate to (7.0, 0.0), which is what I want, otherwise it just comes out as 7.
I feel like I'm making this more complicated than it is, the core.matrix.complex looks like it has extensions for everything in core.matrix and clojure.core, but it doesn't utilize it with the namespace declaration that I have. I'm not that familiar with Clojure protocols, so there is definitely something that I am missing. I just want all three libraries to be included, and to have any and all math be done in the context of complex numbers, i.e 1 = (1.0, 0.0), and (Math/exp (* pi (complex 0 1)) => (-1.0, 0.0)
How can I go about doing this? Sorry if I'm not being clear, I'll try and clear up any questions people have about what I'm asking.
Edit: I've been thinking about the problem, and really the best place to start is the last equation that I listed: Getting e^pi*i to equal -1. If I try to use Math/exp with complex numbers, I get a casting exception.
I'm not familiar with core.matrix.complex but here are some points you are probably not aware of. This is technically not an answer but it's too long to fix in a comment.
core.matrix defined a set of API, in the form of protocols, defined here.
core.matrix.complex does not extend all protocols to complex matrices. For example, the mat/mmul defined here relies on the protocol PMatrixMultiply. But this protocol is not extended to complex matrices.
(+ 3 4) returns (7.0, 0.0) after use-ing complex.core because complex.core rewrote the function/operator +. But I doubt whether you should refer these operators. complex.core is merely a thin wrapper around org.apache.commons.math3.complex.Complex and it knows nothing about matrices. Perhaps you'll be better off using functions/operators in core.matrix API like add.
In one of my CS courses at university we have to work with Racket. Most of my programming time before university I spent with PHP and Java and also JavaScript. I know Racket is a functional programming language, just like JavaScript (Edit: Of course it isn't. But I felt like I was doing 'functional' programming with it, which after seeing the answers, is a wrong perception.) But I still don't understand some fundamental characteristics of Racket (Scheme).
Why are there no 'real' variables? Why is everything a function in Racket/Scheme? Why did the language designers not include them?
What is define-struct? Is it a function? Is it a class? I somehow, because of my PHP background, always think it's a class, but that can't be really correct.
My question here is I want to understand the concept of the language. I personally still think it's really strange and not like anything I worked with before, so my brain tries to compare it with JavaScript, but it just seems so different to me. Parallels/differences to JavaScript would help a lot!
There are 'real' variables in Racket. For example, if you write this
code
(define x 3)
the 'global' variable x will be set to value 3. If you now write
(set! x 4)
the variable x will change its value to 4. So, in Racket you can
have a 'normal' variables like in any 'normal' language, if you
want. The fact is that in Racket the preferred programming style is
functional as opposed to procedural. In functional programming style
variable mutation is discouraged.
define-struct is a Racket macro that you use to define 'structure
template' along with several other things. For example, if you
write:
(define-struct coord (x y))
you just defined a 'structure template' (i.e user type named coord
that have two "slots": x and y). After that, you can now:
create new "instance" of structure coord, for example like this:
(make-coord 2 3)
extract slot value from the structure object:
(coord-x (make-coord 2 3)) ;will return 2
or
(coord-y (make-coord 2 3)) ;will return 3
you can ask if some given object is just that structure. For
example, (coord? 3) will return #f, since 3 is not of type coord
structure, but
(coord? (make-coord 2 3)) ;will return #t
Perhaps the most popular or in-fashion way to program (using languages like C++, Javascript, and Java) has a few characteristics. You may take them for granted as self-evident, the only possible way. They include:
Imperative
You focus on saying "do this step, then this next step" and so on.
Using mutation.
You declare a variable, and keep assigning it different values ("mutate it").
Object-oriented.
You bundle code and data into classes, and declare instances of them as objects. Then you mutate the objects.
Learning Scheme or Racket will help you understand that these aren't the only way to go about it.
It might make your brain hurt at first, in the same way that a philosophy class might cause you to question things you took for granted. However unlike the philosophy class, there will be some practical pay-off to making brain hurt. :)
An alternative:
Functional (instead of imperative). Focus on expressions that return values, instead of making to-do lists of steps.
Immutable. Ditto.
Not object oriented. Using objects of classes can be a good approach to some problems, but not all. If you want to bundle code with data, there are some more general ways to go about it, such as closures with "let over lambda" and so on. Sometimes you don't need all the "baggage" of classes and especially inheritance.
Scheme and Racket make it easy to explore these ideas. But they are not "pure functional" like say Haskell, so if you really want to do imperative, mutable, object-oriented things you can do that, too. However there's not much point in learning Racket to do things the same way you would in Javascript.
Scheme very much has "real" variables.
The difference between a functional language (like Racket) and an imperative language (like JavaScript or PHP) is that in a functional language, you usually don't use mutable state. Variables are better thought of as names for values than as containers that can hold values. Instead of using things like looping constructs to change values in variables, you instead use recursion for flow control.
define-struct is a special syntactic form, kind of like keywords in other languages. (Unlike other languages, in Scheme you can create your own syntactic forms.) It defines a struct type, which is like a class but doesn't have methods. It also defines a number of functions that help you utilize your new struct type.
There are variables in Scheme.
> (define a 1)
#<unspecified>
> a
1
> (set! a 2)
#<unspecified>
> a
2
There are even mutable data structures in this language.
> (begin
> (define v (make-vector 4))
> (vector-set! v 0 'foo)
> (vector-set! v 1 'bar)
> (vector-set! v 2 'baz)
> (vector-set! v 3 'quux))
#<unspecified>
> v
#(foo bar baz quux)
Scheme is not a pure FP language; it does allow imperative programming, although it is mostly geared towards functional programming. That's a design choice that Scheme's inventors made.
define-struct is a special form; it's syntax, like the function or return keywords in JavaScript.
Why is the Haskell implementation so focused on linked lists?
For example, I know Data.Sequence is more efficient
with most of the list operations (except for the cons operation), and is used a lot;
syntactically, though, it is "hardly supported". Haskell has put a lot of effort into functional abstractions, such as the Functor and the Foldable class, but their syntax is not compatible with that of the default list.
If, in a project I want to optimize and replace my lists with sequences - or if I suddenly want support for infinite collections, and replace my sequences with lists - the resulting code changes are abhorrent.
So I guess my wondering can be made concrete in questions such as:
Why isn't the type of map equal to (Functor f) => (a -> b) -> f a -> f b?
Why can't the [] and (:) functions be used for, for example, the type in Data.Sequence?
I am really hoping there is some explanation for this, that doesn't include the words "backwards compatibility" or "it just grew that way", though if you think there isn't, please let me know. Any relevant language extensions are welcome as well.
Before getting into why, here's a summary of the problem and what you can do about it. The constructors [] and (:) are reserved for lists and cannot be redefined. If you plan to use the same code with multiple data types, then define or choose a type class representing the interface you want to support, and use methods from that class.
Here are some generalized functions that work on both lists and sequences. I don't know of a generalization of (:), but you could write your own.
fmap instead of map
mempty instead of []
mappend instead of (++)
If you plan to do a one-off data type replacement, then you can define your own names for things, and redefine them later.
-- For now, use lists
type List a = [a]
nil = []
cons x xs = x : xs
{- Switch to Seq in the future
-- type List a = Seq a
-- nil = empty
-- cons x xs = x <| xs
-}
Note that [] and (:) are constructors: you can also use them for pattern matching. Pattern matching is specific to one type constructor, so you can't extend a pattern to work on a new data type without rewriting the pattern-matchign code.
Why there's so much list-specific stuff in Haskell
Lists are commonly used to represent sequential computations, rather than data. In an imperative language, you might build a Set with a loop that creates elements and inserts them into the set one by one. In Haskell, you do the same thing by creating a list and then passing the list to Set.fromList. Since lists so closely match this abstraction of computation, they have a place that's unlikely to ever be superseded by another data structure.
The fact remains that some functions are list-specific when they could have been generic. Some common functions like map were made list-specific so that new users would have less to learn. In particular, they provide simpler and (it was decided) more understandable error messages. Since it's possible to use generic functions instead, the problem is really just a syntactic inconvenience. It's worth noting that Haskell language implementations have very little list-speficic code, so new data structures and methods can be just as efficient as the "built-in" ones.
There are several classes that are useful generalizations of lists:
Functor supplies fmap, a generalization of map.
Monoid supplies methods useful for collections with list-like structure. The empty list [] is generalized to other containers by mempty, and list concatenation (++) is generalized to other containers by mappend.
Applicative and Monad supply methods that are useful for interpreting collections as computations.
Traversable and Foldable supply useful methods for running computations over collections.
Of these, only Functor and Monad were in the influential Haskell 98 spec, so the others have been overlooked to varying degrees by library writers, depending on when the library was written and how actively it was maintained. The core libraries have been good about supporting new interfaces.
I remember reading somewhere that map is for lists by default since newcomers to Haskell would be put off if they made a mistake and saw a complex error about "Functors", which they have no idea about. Therefore, they have both map and fmap instead of just map.
EDIT: That "somewhere" is the Monad Reader Issue 13, page 20, footnote 3:
3You might ask why we need a separate map function. Why not just do away with the current
list-only map function, and rename fmap to map instead? Well, that’s a good question. The
usual argument is that someone just learning Haskell, when using map incorrectly, would much
rather see an error about lists than about Functors.
For (:), the (<|) function seems to be a replacement. I have no idea about [].
A nitpick, Data.Sequence isn't more efficient for "list operations", it is more efficient for sequence operations. That said, a lot of the functions in Data.List are really sequence operations. The finger tree inside Data.Sequence has to do quite a bit more work for a cons (<|) equivalent to list (:), and its memory representation is also somewhat larger than a list as it is made from two data types a FingerTree and a Deep.
The extra syntax for lists is fine, it hits the sweet spot at what lists are good at - cons (:) and pattern-matching from the left. Whether or not sequences should have extra syntax is further debate, but as you can get a very long way with lists, and lists are inherently simple, having good syntax is a must.
List isn't an ideal representation for Strings - the memory layout is inefficient as each Char is wrapped with a constructor. This is why ByteStrings were introduced. Although they are laid out as an array ByteStrings have to do a bit of administrative work - [Char] can still be competitive if you are using short strings. In GHC there are language extensions to give ByteStrings more String-like syntax.
The other major lazy functional Clean has always represented strings as byte arrays, but its type system made this more practical - I believe the ByteString library uses unsafePerfomIO under the hood.
With version 7.8, ghc supports overloading list literals, compare the manual. For example, given appropriate IsList instances, you can write
['0' .. '9'] :: Set Char
[1 .. 10] :: Vector Int
[("default",0), (k1,v1)] :: Map String Int
['a' .. 'z'] :: Text
(quoted from the documentation).
I am pretty sure this won't be an answer to your question, but still.
I wish Haskell had more liberal function names(mixfix!) a la Agda. Then, the syntax for list constructors (:,[]) wouldn't have been magic; allowing us to at least hide the list type and use the same tokens for our own types.
The amount of code change while migrating between list and custom sequence types would be minimal then.
About map, you are a bit luckier. You can always hide map, and set it equal to fmap yourself.
import Prelude hiding(map)
map :: (Functor f) => (a -> b) -> f a -> f b
map = fmap
Prelude is great, but it isn't the best part of Haskell.
I am new to Scheme Macros. If I just have one pattern and I want to combine the define-syntax and syntax-rules, how do I do that?
(define-syntax for
(syntax-rules (from to)
[(for i from x to y step body) ...]
[(for i from x to y body) ...]))
If I just have one for, how do I combine the syntax definition and the rule?
Thanks.
In other words, you decided that for really only needs one pattern and want to write something like:
(defmacro (for ,i from ,x to ,y step ,body)
; code goes here
)
There is nothing built-in to Scheme that makes single-pattern macros faster to write. The traditional solution is (surprise!) to write another macro.
I have used defsubst from Swindle, and PLT Scheme now ships with define-syntax-rule which does the same thing. If you are learning macros, then writing your own define-syntax-rule equivalent would be a good exercise, particularly if you want some way to indicate keywords like "for" and "from". Neither defsubst nor define-syntax-rule handle those.