|  |  |  | @ -29,7 +29,7 @@ pub enum TaggedType { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 
			
		
	
		
			
				
					|  |  |  |  | pub enum Type { | 
			
		
	
		
			
				
					|  |  |  |  |     TypeVariable(Ident),         // a
 | 
			
		
	
		
			
				
					|  |  |  |  |     Variable(Ident),             // a
 | 
			
		
	
		
			
				
					|  |  |  |  |     Primitive(PrimitiveType),    // Bool | Nat
 | 
			
		
	
		
			
				
					|  |  |  |  |     Arrow(Box<Type>, Box<Type>), // 0 -> 1
 | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
	
		
			
				
					|  |  |  | @ -67,7 +67,7 @@ impl TaggedType { | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn to_concrete(self) -> Option<Type> { | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn into_concrete(self) -> Option<Type> { | 
			
		
	
		
			
				
					|  |  |  |  |         match self { | 
			
		
	
		
			
				
					|  |  |  |  |             TaggedType::Tagged(type_tag, _, tagged_type) => None, | 
			
		
	
		
			
				
					|  |  |  |  |             TaggedType::Concrete(t) => Some(t), | 
			
		
	
	
		
			
				
					|  |  |  | @ -228,7 +228,7 @@ impl From<PrimitiveType> for Type { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl From<&str> for Type { | 
			
		
	
		
			
				
					|  |  |  |  |     fn from(value: &str) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         Self::TypeVariable(value.to_string()) | 
			
		
	
		
			
				
					|  |  |  |  |         Self::Variable(value.to_string()) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -246,7 +246,7 @@ impl Type { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn is_concrete(&self) -> bool { | 
			
		
	
		
			
				
					|  |  |  |  |         match self { | 
			
		
	
		
			
				
					|  |  |  |  |             Type::TypeVariable(_) => false, | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Variable(_) => false, | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Primitive(primitive_type) => true, | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Arrow(t1, t2) => t1.is_concrete() && t2.is_concrete(), | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | @ -254,19 +254,18 @@ impl Type { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn has_tag(&self, tag: &TypeTag) -> bool { | 
			
		
	
		
			
				
					|  |  |  |  |         match self { | 
			
		
	
		
			
				
					|  |  |  |  |             Type::TypeVariable(_) => true, | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Primitive(primitive_type) => match (primitive_type, tag) { | 
			
		
	
		
			
				
					|  |  |  |  |                 (_, TypeTag::Any) => true, | 
			
		
	
		
			
				
					|  |  |  |  |                 (PrimitiveType::Nat, TypeTag::Num) => true, | 
			
		
	
		
			
				
					|  |  |  |  |                 _ => false, | 
			
		
	
		
			
				
					|  |  |  |  |             }, | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Variable(_) => true, | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Primitive(primitive_type) => matches!( | 
			
		
	
		
			
				
					|  |  |  |  |                 (primitive_type, tag), | 
			
		
	
		
			
				
					|  |  |  |  |                 (_, TypeTag::Any) | (PrimitiveType::Nat, TypeTag::Num) | 
			
		
	
		
			
				
					|  |  |  |  |             ), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Arrow(_, _) => false, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn map_name<F: Fn(&mut String)>(&mut self, f: &F) { | 
			
		
	
		
			
				
					|  |  |  |  |         match self { | 
			
		
	
		
			
				
					|  |  |  |  |             Type::TypeVariable(v) => f(v), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Variable(v) => f(v), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Arrow(lhs, rhs) => { | 
			
		
	
		
			
				
					|  |  |  |  |                 lhs.map_name(f); | 
			
		
	
		
			
				
					|  |  |  |  |                 rhs.map_name(f); | 
			
		
	
	
		
			
				
					|  |  |  | @ -277,7 +276,7 @@ impl Type { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn name_used(&self, ident: &str) -> bool { | 
			
		
	
		
			
				
					|  |  |  |  |         match self { | 
			
		
	
		
			
				
					|  |  |  |  |             Type::TypeVariable(i) if *i == ident => true, | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Variable(i) if *i == ident => true, | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Arrow(lhs, rhs) => lhs.name_used(ident) || rhs.name_used(ident), | 
			
		
	
		
			
				
					|  |  |  |  |             _ => false, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | @ -285,7 +284,7 @@ impl Type { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn type_var(&self) -> Option<String> { | 
			
		
	
		
			
				
					|  |  |  |  |         match self { | 
			
		
	
		
			
				
					|  |  |  |  |             Type::TypeVariable(v) => Some(v.clone()), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Variable(v) => Some(v.clone()), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Primitive(primitive_type) => None, | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Arrow(_, _) => None, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | @ -293,7 +292,7 @@ impl Type { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn type_vars(&self) -> HashSet<String> { | 
			
		
	
		
			
				
					|  |  |  |  |         match self { | 
			
		
	
		
			
				
					|  |  |  |  |             Type::TypeVariable(v) => { | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Variable(v) => { | 
			
		
	
		
			
				
					|  |  |  |  |                 let mut set = HashSet::new(); | 
			
		
	
		
			
				
					|  |  |  |  |                 set.insert(v.to_string()); | 
			
		
	
		
			
				
					|  |  |  |  |                 set | 
			
		
	
	
		
			
				
					|  |  |  | @ -311,7 +310,7 @@ impl Type { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn specialize(self, ident: &str, typ: &Type) -> Type { | 
			
		
	
		
			
				
					|  |  |  |  |         match self { | 
			
		
	
		
			
				
					|  |  |  |  |             Type::TypeVariable(i) if i == ident => typ.clone(), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Variable(i) if i == ident => typ.clone(), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Arrow(lhs, rhs) => Type::Arrow( | 
			
		
	
		
			
				
					|  |  |  |  |                 Box::new(lhs.specialize(ident, typ)), | 
			
		
	
		
			
				
					|  |  |  |  |                 Box::new(rhs.specialize(ident, typ)), | 
			
		
	
	
		
			
				
					|  |  |  | @ -344,7 +343,7 @@ impl Display for TaggedType { | 
			
		
	
		
			
				
					|  |  |  |  | impl Display for Type { | 
			
		
	
		
			
				
					|  |  |  |  |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 
			
		
	
		
			
				
					|  |  |  |  |         match self { | 
			
		
	
		
			
				
					|  |  |  |  |             Type::TypeVariable(i) => write!(f, "{i}"), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Variable(i) => write!(f, "{i}"), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Primitive(primitive_type) => write!(f, "{primitive_type}"), | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Arrow(t1, t2) => write!(f, "({t1} -> {t2})"), | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | 
 |