Enum polytype::Type [−][src]
Represents monotypes (fully instantiated, unquantified types).
The primary ways to create a Type
are with either the tp!
macro or
TypeSchema::instantiate
. Type::arrow
constructs function types (i.e. α → β
), as does
conversion (Type::from
) with Vec
and VecDeque
for curried arrows.
Variants
Constructed(N, Vec<Type<N>>)
Primitive or composite types (e.g. int
, List(α)
, α → β
)
Examples
Primitives have no associated types:
let tint = Type::Constructed("int", vec![]); assert_eq!(tint.to_string(), "int")
Composites have associated types:
let tint = Type::Constructed("int", vec![]); let tlist_of_ints = Type::Constructed("list", vec![tint]); assert_eq!(tlist_of_ints.to_string(), "list(int)");
With the macro:
let t = tp!(list(tp!(int))); assert_eq!(t.to_string(), "list(int)");
Function types, or "arrows", are constructed with either Type::arrow
, two
implementations of Type::from
— one for Vec<Type>
and one for VecDeque<Type>
— or
the macro:
let t = Type::arrow(tp!(int), tp!(bool)); assert_eq!(t.to_string(), "int → bool"); let t = Type::from(vec![tp!(int), tp!(int), tp!(bool)]); assert_eq!(t.to_string(), "int → int → bool"); let t = tp!(@arrow[tp!(int), tp!(int), tp!(bool)]); // prefer this over Type::from assert_eq!(t.to_string(), "int → int → bool");
Variable(Variable)
Type variables (e.g. α
, β
).
Examples
// any function: α → β let t = tp!(@arrow[Type::Variable(0), Type::Variable(1)]); assert_eq!(t.to_string(), "t0 → t1");
With the macro:
// map: (α → β) → [α] → [β] let t = tp!(@arrow[ tp!(@arrow[tp!(0), tp!(1)]), tp!(list(tp!(0))), tp!(list(tp!(1))), ]); assert_eq!(t.to_string(), "(t0 → t1) → list(t0) → list(t1)");
Methods
impl<N: Name> Type<N>
[src]
impl<N: Name> Type<N>
pub fn arrow(alpha: Type<N>, beta: Type<N>) -> Type<N>
[src]
pub fn arrow(alpha: Type<N>, beta: Type<N>) -> Type<N>
Construct a function type (i.e. alpha
→ beta
).
Examples
let t = Type::arrow(tp!(int), tp!(bool)); assert_eq!(t.to_string(), "int → bool");
pub fn as_arrow(&self) -> Option<(&Type<N>, &Type<N>)>
[src]
pub fn as_arrow(&self) -> Option<(&Type<N>, &Type<N>)>
If the type is an arrow, get its associated argument and return types.
Examples
let t = tp!(@arrow[tp!(int), tp!(int), tp!(bool)]); if let Some((left, right)) = t.as_arrow() { assert_eq!(left.to_string(), "int"); assert_eq!(right.to_string(), "int → bool"); } else { unreachable!() }
pub fn args(&self) -> Option<VecDeque<&Type<N>>>
[src]
pub fn args(&self) -> Option<VecDeque<&Type<N>>>
If the type is an arrow, recursively get all curried function arguments.
Examples
let t = tp!(@arrow[tp!(int), tp!(int), tp!(bool)]); if let Some(args) = t.args() { assert_eq!(args.len(), 2); assert_eq!(args[0].to_string(), "int"); assert_eq!(args[1].to_string(), "int"); } else { unreachable!() }
pub fn returns(&self) -> Option<&Type<N>>
[src]
pub fn returns(&self) -> Option<&Type<N>>
If the type is an arrow, get its ultimate return type.
Examples
let t = tp!(@arrow[tp!(int), tp!(int), tp!(bool)]); if let Some(ret) = t.returns() { assert_eq!(ret.to_string(), "bool"); } else { unreachable!() }
pub fn apply(&self, ctx: &Context<N>) -> Type<N>
[src]
pub fn apply(&self, ctx: &Context<N>) -> Type<N>
Applies the type in a Context
.
This will substitute type variables for the values associated with them by the context.
Examples
let mut ctx = Context::default(); ctx.unify(&tp!(0), &tp!(int)).expect("unifies"); let t = tp!(list(tp!(0))); assert_eq!(t.to_string(), "list(t0)"); let t = t.apply(&ctx); assert_eq!(t.to_string(), "list(int)");
pub fn apply_mut(&mut self, ctx: &Context<N>)
[src]
pub fn apply_mut(&mut self, ctx: &Context<N>)
Like apply
, but works in-place.
pub fn generalize(&self, bound: &[Variable]) -> TypeSchema<N>
[src]
pub fn generalize(&self, bound: &[Variable]) -> TypeSchema<N>
Generalizes the type by quantifying over free variables in a TypeSchema
.
Variables specified by bound
remain unquantified.
Examples
let t = tp!(@arrow[tp!(0), tp!(1)]); assert_eq!(t.to_string(), "t0 → t1"); let mut ctx = Context::default(); ctx.extend(0, tp!(int)); let t_gen = t.apply(&ctx).generalize(&[]); assert_eq!(t_gen.to_string(), "∀t1. int → t1"); let t_gen = t.apply(&ctx).generalize(&[1]); assert_eq!(t_gen.to_string(), "int → t1");
pub fn vars(&self) -> Vec<Variable>
[src]
pub fn vars(&self) -> Vec<Variable>
Compute all the variables present in a type.
Examples
let t = tp!(@arrow[tp!(0), tp!(1)]); assert_eq!(t.to_string(), "t0 → t1"); let mut vars = t.vars(); vars.sort(); assert_eq!(vars, vec![0, 1]);
pub fn substitute(&self, substitution: &HashMap<Variable, Type<N>>) -> Type<N>
[src]
pub fn substitute(&self, substitution: &HashMap<Variable, Type<N>>) -> Type<N>
Perform a substitution. This is analogous to apply
.
Examples
let t = tp!(@arrow[tp!(0), tp!(1)]); assert_eq!(t.to_string(), "t0 → t1"); let mut substitution = HashMap::new(); substitution.insert(0, tp!(int)); substitution.insert(1, tp!(bool)); let t = t.substitute(&substitution); assert_eq!(t.to_string(), "int → bool");
pub fn substitute_mut(&mut self, substitution: &HashMap<Variable, Type<N>>)
[src]
pub fn substitute_mut(&mut self, substitution: &HashMap<Variable, Type<N>>)
Like substitute
, but works in-place.
pub fn parse(s: &str) -> Result<Type<N>, ()>
[src]
pub fn parse(s: &str) -> Result<Type<N>, ()>
Parse a type from a string. This round-trips with Display
. This is a
leaky operation and should be avoided wherever possible: names of
constructed types will remain until program termination.
Examples
let t_par = Type::parse("int -> hashmap(str, list(bool))").expect("valid type"); let t_lit = tp!(@arrow[ tp!(int), tp!(hashmap( tp!(str), tp!(list(tp!(bool))), )), ]); assert_eq!(t_par, t_lit); let s = "(t1 → t0 → t1) → t1 → list(t0) → t1"; let t: Type<&'static str> = Type::parse(s).expect("valid type"); let round_trip = t.to_string(); assert_eq!(s, round_trip);
Trait Implementations
impl<N: Debug + Name> Debug for Type<N>
[src]
impl<N: Debug + Name> Debug for Type<N>
fn fmt(&self, f: &mut Formatter) -> Result
[src]
fn fmt(&self, f: &mut Formatter) -> Result
Formats the value using the given formatter. Read more
impl<N: Clone + Name> Clone for Type<N>
[src]
impl<N: Clone + Name> Clone for Type<N>
fn clone(&self) -> Type<N>
[src]
fn clone(&self) -> Type<N>
Returns a copy of the value. Read more
fn clone_from(&mut self, source: &Self)
1.0.0[src]
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source
. Read more
impl<N: Hash + Name> Hash for Type<N>
[src]
impl<N: Hash + Name> Hash for Type<N>
fn hash<__HN: Hasher>(&self, state: &mut __HN)
[src]
fn hash<__HN: Hasher>(&self, state: &mut __HN)
Feeds this value into the given [Hasher
]. Read more
fn hash_slice<H>(data: &[Self], state: &mut H) where
H: Hasher,
1.3.0[src]
fn hash_slice<H>(data: &[Self], state: &mut H) where
H: Hasher,
Feeds a slice of this type into the given [Hasher
]. Read more
impl<N: PartialEq + Name> PartialEq for Type<N>
[src]
impl<N: PartialEq + Name> PartialEq for Type<N>
fn eq(&self, other: &Type<N>) -> bool
[src]
fn eq(&self, other: &Type<N>) -> bool
This method tests for self
and other
values to be equal, and is used by ==
. Read more
fn ne(&self, other: &Type<N>) -> bool
[src]
fn ne(&self, other: &Type<N>) -> bool
This method tests for !=
.
impl<N: Eq + Name> Eq for Type<N>
[src]
impl<N: Eq + Name> Eq for Type<N>
impl<N: Name> Display for Type<N>
[src]
impl<N: Name> Display for Type<N>
fn fmt(&self, f: &mut Formatter) -> Result<(), Error>
[src]
fn fmt(&self, f: &mut Formatter) -> Result<(), Error>
Formats the value using the given formatter. Read more
impl<N: Name> From<VecDeque<Type<N>>> for Type<N>
[src]
impl<N: Name> From<VecDeque<Type<N>>> for Type<N>
impl<N: Name> From<Vec<Type<N>>> for Type<N>
[src]
impl<N: Name> From<Vec<Type<N>>> for Type<N>