I have a logical clause like this:
exists l.(language(l) & exists n.(name(n) & :op1(n,"English") & :name(l,n)))
which corresponds to the expression: "language is English"
The clause consists of the variables (l,n), predicates (language, name, op1) and constants ("English"). Each variable is assigned to its corresponding class first (l is assigned to "language" and n is assigned to "name") then the instance of a class is used for further inference (:op1 is a predicate assigning the constant "English" to the instance of the class "language". Or it can be considered as a property of a class "language").
Is there a way to convert this into LEAN code?
There are many ways you might map this into Lean, and it can depend greatly on what you're wanting to model exactly. In any case, here's one possibility.
Lean uses type theory, and one difference between type theory and first-order logic is that quantification is always bounded by a type, rather than there being a universal domain of discourse. Maybe the most idiomatic way to write this is as
namespace lang_ex
inductive language
| english
def name : language → string
| language.english := "English"
end lang_ex
This defines a new type called language that has one inhabitant called language.english, and it defines a function name that takes something with type language and yields a string (standing in for your name class). The rule for the function is that its value when given language.english is "English".
What these directives do, more or less, is define the following axioms:
namespace lang_ex
constant language : Type
constant language.english : language
constant name : language → string
axiom name_english : name language.english = "English"
end lang_ex
(There's no difference between constant and axiom -- they both introduce things axiomatically.) In Lean, function application syntax is by juxtaposition, so name language.english rather than name(language.english).
Here's an unidiomatic way to write it, following your clause as closely as possible:
namespace lang_ex
constant univ : Type
constant is_language : univ → Prop
constant is_name : univ → Prop
constant op1 : univ → string → Prop
constant name : univ → univ → Prop
axiom clause :
∃ (l : univ), is_language l ∧
∃ (n : univ), is_name n ∧ op1 n "English" ∧ name l n
end lang_ex
Related
In imperative programming, there is concise syntax sugar for changing part of an object, e.g. assigning to a field:
foo.bar = new_value
Or to an element of an array, or in some languages an array-like list:
a[3] = new_value
In functional programming, the idiom is not to mutate part of an existing object, but to create a new object with most of the same values, but a different value for that field or element.
At the semantic level, this brings about significant improvements in ease of understanding and composing code, albeit not without trade-offs.
I am asking here about the trade-offs at the syntax level. In general, creating a new object with most of the same values, but a different value for one field or element, is a much more heavyweight operation in terms of how it looks in your code.
Is there any functional programming language that provides syntax sugar to make that operation look more concise? Obviously you can write a function to do it, but imperative languages provide syntax sugar to make it more concise than calling a procedure; do any functional languages provide syntax sugar to make it more concise than calling a function? I could swear that I have seen syntax sugar for at least the object.field case, in some functional language, though I forget which one it was.
(Performance is out of scope here. In this context, I am talking only about what the code looks like and does, not how fast it does it.)
Haskell records have this functionality. You can define a record to be:
data Person = Person
{ name :: String
, age :: Int
}
And an instance:
johnSmith :: Person
johnSmith = Person
{ name = "John Smith"
, age = 24
}
And create an alternation:
johnDoe :: Person
johnDoe = johnSmith {name = "John Doe"}
-- Result:
-- johnDoe = Person
-- { name = "John Doe"
-- , age = 24
-- }
This syntax, however, is cumbersome when you have to update deeply nested records. We've got a library lens that solves this problem quite well.
However, Haskell lists do not provide an update syntax because updating on lists will have an O(n) cost - they are singly-linked lists.
If you want efficient update on list-like collections, you can use Arrays in the array package, or Vectors in the vector package. They both have the infix operator (//) for updating:
alteredVector = someVector // [(1, "some value")]
-- similar to `someVector[1] = "some value"`
it is not built-in, but I think infix notation is convenient enough!
One language with that kind of sugar is F#. It allows you to write
let myRecord3 = { myRecord2 with Y = 100; Z = 2 }
Scala also has sugar for updating a Map:
ms + (k -> v)
ms updated (k,v)
In a language such as Haskell, you would need to write this yourself. If you can express the update as a key-value pair, you might define
let structure' =
update structure key value
or
update structure (key, value)
which would let you use infix notation such as
structure `update` (key, value)
structure // (key, value)
As a proof of concept, here is one possible (inefficient) implementation, which also fails if your index is out of range:
module UpdateList (updateList, (//)) where
import Data.List (splitAt)
updateList :: [a] -> (Int,a) -> [a]
updateList xs (i,y) = let ( initial, (_:final) ) = splitAt i xs
in initial ++ (y:final)
infixl 6 // -- Same precedence as +
(//) :: [a] -> (Int,a) -> [a]
(//) = updateList
With this definition, ["a","b","c","d"] // (2,"C") returns ["a","b","C","d"]. And [1,2] // (2,3) throws a runtime exception, but I leave that as an exercise for the reader.
H. Rhen gave an example of Haskell record syntax that I did not know about, so I’ve removed the last part of my answer. See theirs instead.
I'm reading lambdasoup/soup.ml at master · aantron/lambdasoup · GitHub but I don't understand the syntax.
and 'a node =
{mutable self : 'b. 'b node option;
mutable parent : general node option;
values : [ `Element of element_values
| `Text of string
| `Document of document_values ]}
I don't understand 'b. 'b node option, if it was * it would be a tuple but it's the first time I see with . Also why the back-tic in the branches (e.g. `Element)?
The type 'a . type is a type that is explicitly polymorphic in 'a. So your example 'b . 'b node option is explcitly a field whose contents are polymorphic. In other words, any value assigned to the field must itself be polymorphic.
Here's an example with list rather than node:
type a = { mutable self : 'b. 'b list option; }
# let x = { self = None };;
val x : a = {self = None}
# x.self <- None;;
- : unit = ()
# x.self <- Some [];;
- : unit = ()
# x.self <- Some [3];;
Error: This field value has type int list option
which is less general than 'b. 'b list option
#
You can assign None to x.self because None is polymorphic (its type is 'a option, which works for any option type). You can assign Some [] to x.self because it's also polymorphic (its type is 'a list option, which works for any optional list). But you can't assign Some [3] to x.self because its type is int list option; in other words, it's not polymorphic.
You can find a discussion of explicitly polymorphic types in Section 5.2.1 of the OCaml manual.
Variant values with leading backquote like `A or `B are so-called polymorphic variants. This is a different feature than the usual variant types. The basic idea is that a polymorphic variant represents a value that is not necessarily part of any predefined type. The associated types are essentially sets of these values. Polymorphic variants can also be constructors as in your example type; that is, they can take an associated value. Just as you can have Some "yes", your definition allows one to have `Text "yes".
You can find some discussion of polymorphic variants in Section 7.4 of the OCaml manual (search for "polymorphic variant types").
I am trying to input a schema into Isabelle however when I add range restriction or domain restriction into the theorem prover it doesn't want to parse. I have the following schema in LaTeX:
\begin{schema}{VideoShop}
members: \power PERSON \\
rented: PERSON \rel TITLE \\
stockLevel: TITLE \pfun \nat
\where
\dom rented \subseteq members \\
\ran rented \subseteq \dom stockLevel \\
\forall t: \ran rented # \# (rented \rres \{t\}) \leq stockLevel~t
\end{schema}
When inputting this into Isabelle I get the following:
locale videoshop =
fixes members :: "PERSON set"
and rented :: "(PERSON * TITLE) set"
and stockLevel :: "(TITLE * nat) set"
assumes "Domain rented \<subseteq> members"
and "Range rented \<subseteq> Domain stockLevel"
and "(\<forall> t. (t \<in> Range rented) \<and> (card (rented \<rhd> {t}) \<le> stockLevel t))"
begin
.....
It all parses except for the last expression \<forall> t.....
I just don't understand how to add range restriction into Isabelle.
There are multiple problems with your input.
The ⊳ symbol you are using in the expression
(rented ⊳ {t})
is not associated with any operator, so it can't be parsed. I'm not quite sure what it's supposed to mean. From the high-level idea of the specification I'm guessing something along the lines of "all persons who rented a specific title". This can be expressed most easily with a set comprehension:
{p. (p, t) ∈ rented}
You translated the bounded universal quantifier into a quantifier containing a conjunction. This is likely not what you want, because it says "for all t, t is in the range of rented and something else". Isabelle has notation for bounded quantifiers.
∀t ∈ Range rented. ...
You are trying to use stockLevel as a function, which it isn't. From your LaTeX input I gather that it's supposed to be a partial function. Isabelle calls these maps. The appropriate type is:
TITLE ⇀ nat
Note the "harpoon" symbol instead of a function arrow. The domain function for maps is called dom. The second locale assumption can be expressed as:
Range rented ⊆ dom stockLevel
Given that, you can use stockLevel as a function from TITLE to nat option.
If A isRelatedTo B
and B has the dataproperty: existence = {true, false}
how can I express in manchester owl syntax (for protege) the subset where:
is type A and
every isRelatedTo of A has the value "true"
I think what you're asking is how to write the class expression for the class whose members have type A and all of whose values for the isRelatedTo property is true^^xsd:boolean. That's simple enough:
A and (isRelatedTo only {true})
In Protégé it looks like this:
I'm trying to define a function on a weakly-specified type in Coq. Specifically, I have a type that is defined inductively by a set of recursive constructors, and I want to define a function that is only defined when the argument has been constructed using a subset of these.
To be more concrete, I have the following type definition:
Inductive Example : Set :=
| Example_cons0 : nat -> Example
| Example_cons1 : Example -> Example
.
Now, I have a function that only applies to the ground case. (The following definition will not work obviously, but is meant to suggest my intent.)
Definition example (x:Example) : nat :=
match x with
| Example_cons0 n => n
end.
Ideally, I'd like to communicate that my argument, x, has been constructed using a subset of the general type constructors, in this case, Example_cons0. I thought that I could do this by defining a predicate that states this fact and passing a proof of the predicate as an argument. For example:
Definition example_pred (x:Example) : Prop :=
match x with
| Example_cons0 _ => True
| _ => False
end.
And then (following the recommendation given by Robin Green) something like,
Definition example2 (x:Example) : example_pred x -> nat :=
(use proof to define example2?)
Unfortunately, I'm not sure how I would go about doing any of this. I'm not even sure that this is the correct way to define restricted functions on weakly-specified types.
Any guidance, hints, or suggestions would be strongly appreciated!
- Lee
Update:
Following recommendations by jozefg, the example function can be defined as:
Definition example (x:Example) : example_pred x -> nat :=
match x with
| Example_cons0 n => fun _ => n
| _ => fun proof => match proof with end
end.
See his comments for details. This function can be evaluated using the following syntax, which also demonstrates how proof terms are represented in Coq:
Coq < Eval compute in Example.example (Example.Example_cons0 0) (I : Example.example_pred (Example.Example_cons0 0)).
= 0
: nat
Here's how I'd write this as a simplified example
Consider a simple data type
Inductive Foo :=
| Bar : nat -> Foo
| Baz.
And now we define a helpful function
Definition bar f :=
match f with
| Bar _ => True
| Baz => False
end.
And finally what you want to write:
Definition example f :=
match f return bar f -> nat with
| Bar n => fun _ => n
| Baz => fun p => match p with end
end.
This has the type forall f : Foo, bar f -> nat. This works by making sure that in the case that example was not supplied a Bar, that the user must supply a proof of false (impossible).
This can be called like this
example (Bar n) I
But the problem is, you may have to manually prove some term is constructed by Bar, otherwise how is Coq supposed to know?
Yes, you are on the right lines. You want:
Definition example2 (x:Example) (example_pred x) : nat :=
and how to proceed further would depend on what you wanted to prove.
You might find it helpful to make a definition by proving with tactics, using the Curry-Howard correspondence:
Definition example2 (x:Example) (example_pred x) : nat.
Proof.
some proof
Defined.
Also, I'd like to point out that the sig and sigT types are often used to combine "weakly-specified types" with predicates to constrain them.