Reputation: 105
Today we mentioned type variable. But I don't understand what it means. I can only find one explanation on wiki, type variable
I understand the explanation in math, but still, have no idea about programming. Can anyone give an explanation?
Upvotes: 0
Views: 3602
Reputation: 327
With Type variables you can define a datatype/container for things (Numbers, Text, ...) of a non-specified type. To provide an easy example, imagine, you want a Box, where you can put in anything you want.
Here is an example in Java (T is the type-variable):
public class Box<T> {
private T thing;
public void putThing(T thing) {
this.thing = thing;
}
}
Here is an example in Haskell (a is the type-variable):
data Box a = PutThing a
Another good example would be a generic tuple datatype.
Example usecases
Note, in both cases the type-variables are now specified types.
Java:
Box<String> box = new Box<String>();
box.putThing("42");
Haskell (in ghci):
:t (PutThing (42::Int))
(PutThing (42::Int)) :: Box Int
Upvotes: 3
Reputation: 303
The example from wikipedia can be written in Java like this
public static <T> T identity(T a) {
return a;
}
where the type of a
is bound to the type parameter T
. So when you call the identity function with an Integer
you get back an Integer
, when you call it with a String
you get back a String
.
A very common usage example would be a collection of values of the same type like a list of Strings:
List<String> as = new ArrayList<String>();
The type parameter in the List
interface is bound to String
therefore all elements of that list must be of type String
.
Updated code snippet, thanks Elliott.
Upvotes: 2
Reputation: 1741
A type variable is a way to have polymorphism by writing a single function/method that works on multiple different types of values. Here is an example in Haskell:
id :: forall a. a -> a
id x = x
The a
in the type signature is a type variable, and as the forall
implies, this function works "for all" different types. For example, you can use id
as if it had the type Int -> Int
or as if it had the type Char -> Char
.
id (5 :: Int) = 5 :: Int
id 'a' = 'a'
If id
was given a concrete type (meaning without type variables in it) such as id :: Int -> Int
, then id 'a'
would be a type error because 'a'
's type (Char
) doesn't match Int
.
Usually, we omit the forall
(id :: a -> a
) because it can easily be inferred from the use of type variables, but it is helpful for understanding what is really going on.
I don't know as much Java as Haskell, but Generics seems to be a way to use a type variable, so ArrayList<A>
means an array list that works for any non-primitive type A
.
Upvotes: 1
Reputation: 36329
Well, it's very easy. The basic observation is that we do not only have basic types like Int and Bool and Char, but types composed from other types.
The simplest example are lists. In a type safe language, all elements of a list must have the same type. That is why we write:
Haskell Java Explanation
[Int] List<Integer> list of integers
[Char] List<Character> list of characters
and so on. This is nice already, but not nice enough. It turns out that certain functions on lists are absolutely identical except for the element type, and that the element type is irrelevant inside the function. Here is an example:
lengthIntList :: [Int] -> Int -- compute length of a list of int
lengthIntList [] = 0
lengthIntList (x:xs) = 1 + length xs
lengthCharList :: [Char] -> Int -- compute length of a list of char
lengthCharList [] = 0
lengthCharList (x:xs) = 1 + length xs
Therefore, the next step is to abstract from the element type and say:
length :: [a] -> Int -- length of a list, for all elemen types
length [] = 0
length (x:xs) = 1 + length xs
Here, the a
is a type variable that says: For all types, this function length
takes a list of that type and returns an Int
.
Upvotes: 2