Starting with an Agda module that only define a type as a postulate
module M where
postulate
U : Set
I want to be able to define U in different ways. For example:
module B where
open M public
-- define U as Bool
and
module N where
open M public
-- define U as Nat
Is there a way to do this in Agda?
AFAIK, you can't, postulates are abstract.
You can achieve what you want by inverting the order: instead of trying to define U inside a module B or N like you do, instead do
module M (U : Set) where
and then you instantiate U to Bool or Nat.
Related
It's folk knowledge that OCaml modules are "just" existential types. That there's some kind of parity between
module X = struct type t val x : t end
and
data 'a spec = { x : 'a }
data x = X : 'a spec
and this isn't untrue exactly.
But as I just evidenced, OCaml has both modules and existential types. My question is:
How do they differ?
Is there anything which can be implemented in one but not the other?
When would you use one over the other (in particular comparing first-class modules with existential types)?
Completing gsg's answer on your third point.
There are two kinds of way to use modules:
As a structuring construct, when you declare toplevel modules. In that case you are not really manipulating existential variables. When encoding the module system in system-F, you would effectively represent the abstract types by existential variables, but morally, it is closer to a fresh singleton type.
As a value, when using first class modules. In that case you are clearly manipulating existential types.
The other representations of existential types are through GADT's and with objects. (It is also possible to encode existential as the negation of universal with records, but its usage are completely replaced by first class modules).
Choosing between those 3 cases depend a bit in the context.
If you want to provide a lot of functions for your type, you will prefer modules or objects. If only a few, you may find the syntax for modules or objects too heavywheight and prefer GADT. GADT's can also reveal a the structure of your type, for instance:
type _ ty =
| List : ty -> ty list
| Int : int list
type exist = E : 'a ty * 'a -> exist
If you are in that kind of case, you do not need to propagate the function working on that type, so you will end up with something a lot lighter with GADT's existentials. With modules this would look like
module type Exist = sig
type t
val t : t ty
end
module Int_list : Exist = struct
type t = int list
let t = List Int
end
let int_list = (module Int_list:Exist)
And if you need sub-typing or late binding, go for the objects. This can often be encoded with modules but this tend to be tedious.
It's specifically abstract types that have existential type. Modules without abstract types can be explained without existentials, I think.
Modules have features other than abstract types: they act as namespaces, they are structurally typed, they support operations like include and module type of, they allow private types, etc.
A notable difference is that functors allow ranging over types of any (fixed) arity, which is not possible with type variables because OCaml lacks higher kinded types:
module type M = sig
type 'a t
val x : 'a t
end
I'm not quite sure how to answer your last question. Modules and existentials are different enough in practice that the question of when to substitute one for the other hasn't come up.
Lets say I am given an object O on some method.
This object O is derived from a base Object BaseClass and as such has a part whose type is BaseClass.
How can I access this part when I am in this method, which means super wont work because I am not in the context of the object.
Thanks!
Let me re-phrase your question to make sure I understand it. You have a class O containing a method (say "test"). In that method, you want to access an instance variable belonging to the superclass BaseClass.
If this is correct, then you can already access that instance variable directly. You just need to provide the name of the variable. Your subclass has access to all of the instance variables visible to the superclass.
You should consider creating get and set methods for the variable and accessing the variable by calling those methods from the subclass, but it's optional.
Let me provide another answer, which could be useful for cases where the question refers to behavior (methods) rather than shape (instance variables.)
Assume you have two classes C and D and an instance c of C. Now assume C inherits from C' and you would like to invoke a method m defined in C' that has been overridden in C. The expression c m will activate the implementation in C rather than the one in C' because c class == C, not C'. As you said, there is no "remote" version of super that you could use from D.
If what you want is to activate the method in C', then you should move the source code of m in C' to another method, say m0, and redefine m in C' so that it just delegates to m0 (^self m0). Keep the method m in C unchanged and then call from D using m0 (c m0) instead of m (c m).
Note that the other way around will not work: if you define m0 in C' as ^self m, the expression c m0 will activate the version of m found in C, not C'.
You could also define m0 in C as ^super m and that way c m0 will activate C'>>m. However, the usage of super with a different selector is not considered a good practice, and you should chose not to do that.
Is it possible in OWL to add a property onto a single class? So far, I see properties joining a pair of classes (like defining whether or not properties are symmetric, etc.). For example, what kind of property would I use to tag whether or not an animal is a pest. If it matters, I'm using Protégé to construct the ontology.
If your question is whether or not a property can have same domain and range, then yes, it is possible.
If X is a class and p is a property, it is possible to have
p range X
p domain X
and an assertion would look like:
i type X // an instance of X
i p i // a self assertion
I'm not sure how this fits your example though: how are you modeling 'being a pest'? It looks to me like you could model this as
i type Pest
e.g., as a class assertion not a property.
In the project I have several different types, defined in different modules and each of them has related functions (the functions have the same name and very similar meaning, so the following make sense). Now I want to create a list, in which it will be possible to have instances of all these types (simultaneously). The only possibility I can think of is something like this:
data Common = A{...} | B{...} | ...
but it implies keeping the definition in a single place, and not in different modules (for A, B, ...). Is there a better way to do this?
UPD
I'm rather new to haskell and write some programs related to my studying. In this case I have different FormalLanguage definition methods: FiniteAutomata, Grammars and so on. Each of them has common functions (isAccepted, representation, ...), so it seemed logical to have a list where elements can be of any of these types.
You are bringing an OOP mindset to Haskell by assuming the correct solution is to store distinct types in a list. I'll begin by examining that asssumption.
Usually we store distinct types in a homogeneous list because they support a common interface. Why not just factor out the common interface and store THAT in the list?
Unfortunately, your question does not describe what that common interface is, so I will just introduce a few common examples as demonstrations.
The first example would be a bunch of values, x, y, and z, that all support the Show function, which has the signature:
(Show a) => a -> String
Instead of storing the type we want to show later on, we could instead just call show directly on the values and store the resulting strings in the list:
list = [show x, show y, show z] :: String
There's no penalty for calling show prematurely because Haskell is a lazy language and won't actually evaluate the shows until we actually need the string.
Or perhaps the type supports multiple methods, such as:
class Contrived m where
f1 :: m -> String -> Int
f2 :: m -> Double
We can transform classes of the above form into equivalent dictionaries that contain the result of partially applying the methods to our values:
data ContrivedDict = ContrivedDict {
f1' :: String -> Int,
f2' :: Double }
... and we can use this dictionary to package any value into the common interface we expect it to support:
buildDict :: (Contrived m) => m -> ContrivedDict
buildDict m = ContrivedDict { f1' = f1 m, f2' = f2 m }
We can then store this common interface itself in the list:
list :: [buildDict x, buildDict y, buildDict z]
Again, instead of storing the distinctly-typed values, we've factored out their common elements for storage in the list.
However, this trick won't always work. The pathological example is any binary operator that expect two operands of equal type, such as the (+) operator from the Num class, which has the following type:
(Num a) => a -> a -> a
As far as I know, there is no good dictionary-based solution for partially applying a binary operation and storing it in such a way that it guarantees it is applied to a second operand of the same type. In this scenario the existential type class is probably the only valid approach. However, I recommend you stick to the dictionary-based approach when possible as it permits more powerful tricks and transformations than the type-class-based approach.
For more on this technique, I recommend you read Luke Palmer's article: Haskell Antipattern: Existential Typeclass.
There are few possibilities:
Possibility 1:
data Common = A AT | B BT | C CT
with AT, BT and CT described in their respective modules
Possibility 2:
{-# LANGUAGE ExistentialQuantification #-}
class CommonClass a where
f1 :: a -> Int
data Common = forall a . CommonClass a => Common a
which is almost the same as OOP superclass, but you cannot do "downcasts". You can then declare implementations for members of common classes in all the modules.
Possibility 3 suggested by #Gabriel Gonzalez:
data Common = Common {
f1 :: Int
}
So your modules implement common interface by using closures to abstract over the 'private' part.
However, Haskell design is usually radically different from OOP design. While it's possible to implement every OOP trick in Haskell, it will be likely non-idiomatic, so as #dflemstr said more information about your problem is welcome.
interface I1 { ... }
interface I2 { ... }
struct List(T) { ... }
How do I specialize my List to operate only on classes that implement both I1 and I2? One interface is easy:
struct List(T : I1)
Other languages. In C# it's:
struct List<T> where T : I1, I2
And in Java I'd say:
class List<T extends I1 & I2>
One catch: I don't want an if template constraint because I want reasonable auto-completion from a non-state-of-the-art IDEs. I think it'll be long before IDEs for D do things like reverse-engineering template constraints to deduce a list possible T's methods. And even if, that doesn't sound like cheap performance-wise.
If you don't want to constrain template by if statement, only way is this:
struct List(T : I1, U : I2 = T) { }
that means that you can instantiate List with one or two arguments, if you instantiate only with one - List!(C), then the U will be by default assigned value C, and checked if it implements I2. You can then ignore parameter U in the struct. The problem with this method is that you instantiate the List with two parameters - List!(C1, C2)...
Here is version with if constraint, which doesn't have this problem:
struct List2(T) if ( is(T : I1) && is(T : I2)) { }
There is no practical performance overhead in using if template constraint - or any compile time technique - if you are not calculating lot of data (like ct raytracer or look-up tables)
I would really suggest you to not limit your code to what the IDE supports - there sure will be many things that your IDE is not supporting well and you may find yourself having much less fun than using simple text editor with only sintax highlight, but with full potential of D.
In D2, you can use template constraints and the is expression.
struct List(T)
if (is(T : I1) && is(T : I2))
{
...
}
Here, the is expressions checks whether T is implicitly convertible to I1 and I2 (which is only possible if T implements them).