giving a name to a composite type in Rascal (a la typedef) - typedef

In Rascal, how do I introduce a name for a composite type (that's constructed from built-in basic types and type constructors like list and map)?
E.g. I'd like to do something like
typedef IntList = list[int];
typedef StrToIntList = map[str,IntList];
StrToIntList mymap = ();

Instead of typedef you can use alias. For instance:
rascal>alias IntList = list[int];
ok
rascal>alias StrToIntList = map[str,IntList];
ok
rascal>StrToIntList mymap = ();
StrToIntList: ()
You can use alias to give alternate names to existing basic types as well, so you could also do something like:
alias ID = int;
And, you can include type parameters if needed, so a graph over an arbitrary type could be defined as:
alias Graph[&T] = rel[&T,&T];
Note that an alias introduces a type equivalence and not just a sub-type. So for any function that accepts the alias as argument type, you can also provide a value of the type that it aliases, or any of its sub-types.

Related

Given a Type, create an Option Type that contains it

Given a Type named inner, I would like to create a new Type that represents an Option containing a type of the same type as inner.
For example, the signature of a method that would do this may look something like:
def createOptionType(inner: Type): Type = {
typeOf[Option[inner]] // this line is pseudocode
}
This answer helps partially, but makes use of a generic method, whereas in this case I have a concrete type passed in, making generics unuseable.
You can use scala.reflect.runtime.universe.appliedType for that:
import scala.reflect.runtime.universe._
def createOptionType(inner: Type): Type =
appliedType(typeOf[Option[_]], inner)

Scala Compile Error

I have trouble in building the following code:
type graph_t = scala.collection.mutable.Map[Long, (Long, Float)];
var graph : graph_t = graph_t();
However, it does work by replacing the graph_t() with the original type:
var graph : graph_t = scala.collection.mutable.Map[Long, (Long, Float)] ();
Any answer will be appreciated.
Scala knows two namespaces: types and values. Types define what values are capable of, and values are the things you call methods on.
graph_t() is a method call (the apply method), but you did not define a value called graph_t, you defined a type called graph_t, and you cannot call methods on types.
The reason scala.collection.mutable.Map[Long, (Long, Float)] () works is because scala.collection.mutable.Map is both a type and a value.
That's interesting. Try this:
type s = String;
var x = s()
You get the same error: not found.
That's is because the name of the class is both the name of the type and the name of the constructor, but the name of a type is not necessarily the name of a constructor.
In this case, the function Map actually constructs a concrete implementation of the Map abstract class.

Type alias for mix-in type

Since I can do this:
case class A(a: Int)
trait C
val x = new A(10) with C
Why can't I do this:
type X = A with C
val x = new X(10)
? If I can't even construct an instance, what's the use case of type X = A with C?
The error message that you get should give you a hint:
error: class type required but A with C found
new X(10)
^
X, as a type alias, gets rewritten to an A with C type expression, which is not a class type. The latter, according to the Scala Language Specification, is:
a type designator
(ยง
3.2.3
) that refers to a a class or a trait
(emphasis mine)
In other words, it's not every type expression.
This is not an authoritative answer, but I don't believe it's possible to define a type alias in such a way that it becomes a class type. On the one hand, a new expression theoretically accepts an AnnotType, as defined in Section 5.1.1. However, I don't see how, using the type alias grammar from Section 4.3, you could specify what constructor are you using etc..
tl;dr - unless your type alias is directly rewritable to a class type (e.g. A in your example), you can't use it as a class type, which includes invoking new with it. If you want that, you need a class declaration, i.e. class X(a: Int) extends A(a) with C.
Regarding your second question, you say you can't instantiate X. Ah, but that's where you're wrong! Let me show you an example, based on your code:
def blah(x: X) = x.toString
val x = new A(10) with C
val y = new A(10)
blah(x) //String = A(10)
blah(y) //type error
So, it's useful whenever you need a type constraint, since the "aliased" type will be matched to the type alias, even if it wasn't explicitly declared as such.

Records with similar fields in OCaml

In this answer, the suggested way of "attaching" meta information to types was using a record:
type _foo = ...
and foo = {n:_foo; m:meta}
but what if I have multiple types I'd like to wrap with meta information? Apparently all field names in record types must have different names, and writing:
type _foo = ...
and foo = {n:_foo; m:meta}
...
type _fooX = ...
and fooX = {nX:_fooX; mX:meta}
seems redundant :/. Classes are the only way to solve this? I'd like to avoid dealing with classes, if possible.
You can use parameterized type, perhaps.
type 'a wrapped = { base: 'a; extra: meta }
Jeffrey's solution is correct and scales perfectly to recursive types.
type location
type 'a loc = { a : 'a; loc : location }
type exp = Int of int | Add of exp loc * exp loc
It is still possible to use the previous two-time definition of your type,
as follows:
type exp_data = Int of int | Add of exp * exp
and exp = exp_data loc
Finally, a slightly different style is to use "open recursion", that is to define only an "derecursified type" open_exp with free parameters instead of recursive occurences. You can then get the recursive type back by taking the fixpoint; you can take different fixpoint, one with no additional information, and one with location interleaved for example. This is a generic construction to insert information at recursion sites, and its term-level counterpart allows for weaving different things in a recursive function (memoization, profiling, debug, etc.).
type 'e open_exp = Int | Add of 'e * 'e
type simple_exp = Simple of simple_exp open_exp
type located_exp = Loc of located_exp loc open_exp

OCaml types with different levels of specificity

I am attempting to simulate an interface in OCaml and am using the "type" construct. I have two types:
type fooSansBar = {a: string; b: int};;
type fooConBar = {a:string; b:int; bar:char};;
...and would like to define a particular fooSansBar:
let fsb = {a="a"; b=3};;
...but am told that the bar field is not defined. From this, it appears that, contrary to the values I passed in matching fooSansBar's signature, the system believes I am trying to create a fooConBar. Is it possible to create a fooSansBar if the two types as defined above exist?
Additionally (because I'm new to OCaml) is there a better way to simulate an interface?
In OCaml, field names in record types must be unique, so the two types you define cannot coexist simultaneously. Caml is the only language I know with this property.
Because the second definition hides the first, when the compiler sees the a and b fields it expects them to belong to the fooConBar type and so complains of the missing bar field.
If you are trying to simulate an interface, the correct functional way to do it in Caml is to define a module type.
module type FOO_CON_BAR = sig
val a : string
val b : int
val bar : char
end
And an instance:
module Example = struct
let a = "hello"
let b = 99
let c = '\n'
end
With modules and module types you also get subtyping; there's no need to resort to objects.
P.S. My Caml is rusty; syntax may be off.
There are several possible solutions in OCaml depending how you're using the code you gave. The simplest is to combine the two types:
type fooBar = { a: string; b: int; bar: char option }
Another solution is to replace the records with objects because objects support subtyping (and can have their types inferred so there is no need to declare a type!):
# let fsb = object
method a = "a"
method b = 3
end;;
val fsb : < a : string; b : int > = <obj>
# fsb#a, fsb#b;;
- : string * int = ("a", 3)
The second type redefines a and b, effectively hiding the first, which is why it cannot be constructed any more. You could define these types in different modules, but that would be the same as using a different name for a and b.
These constructs can only be used when you do not try to "derive" from another interface, but just implement it.
If you wish to use these object oriented concepts in Ocaml, you could look at the object system, or, depending on your problem, the module system. Alternatively, you could try to solve your problem in a functional way. What problem are you trying to solve?
OCaml provides two ways to implement interfaces. One, as already mentioned, is a module type.
The other is a class type. You can write a class type (interface) fooSansBar:
class type fooSansBar = object
method a: string
method b: int
end
and a class type fooConBar:
class type fooConBar = object
inherit fooSansBar
method bar: char
end
This will allow you to use a fooConBar anywhere a fooSansBar is required. You can now create a fooSansBar, using type inference:
let fsb = object
method a = "a"
method b = 3
end
Now, fsb's type happens to be <a: string; b: int>, as indicated by Jon, but it's perfectly usable as a fooSansBar due to OCaml's structural subtyping.
In OCaml, it's not possible to have two record types with intersecting field sets present in the same scope.
If you really need to use record types with intersecting field sets, then you can work around this restriction by enclosing the types within their own dedicated modules:
module FooSansBar = struct type t = {a:string; b:int} end
module FooConBar = struct type t = {a:string; b:int; bar:char} end
Then you can construct instances of these types like so:
let fsb = {FooSansBar.a="a"; b=3}
let fcb = {FooConBar.a="a"; b=4; bar='c'}
These instances have the following types:
fsb : FooSansBar.t
fcb : FooConBar.t