Typeclasses
- Applications
- Canonical Structures
- Unification Hints
- Diamonds
- Overlapping
- Multiparameter
- Traits
- Functional Dependencies
- Associated Types
- Prolog
Applications
basic 1 parametr type classes
class Eq a
class Coerc a b
class Collect e ce
# How to make ad-hoc polymorphism less ad-hoc - wadler and Blott the OG.
Quantified class constraints harrop extension to typeclass clauses
types and typeclasses typing haskell in haskell let should not be generalized - hindley milner let eneralization is a pain. Interesting disucssion of local equalities for gadts. ocal equalities is an interedting challenge. Can lambda prolog even do this?
main :- (X = [] => print X), (X = [1] => print X).
Overloading with runtime evidence. Everything has tags, tags are unbundled. Tags are structural? Just ship the dictionary of operatios
Canonical Structures
Typeclasses vs Canonical Structures. I don’t get it. Could I make a model? Maybe in prolog? Diamond problem Inheritance. What are typeclasses? “Kind of like prolog” Things are incompatible for some reason? Canonical structures add unification hints? canonical structures ofr the working coq user - mahboubi tassi
How to Make Ad Hoc Proof Automation Less Ad Hoc Type parameters on the outside vs inside. Canonical structures have them inside. packed records
Dependently Typed Records for Representing Mathematical Structure - Pollack “pebble style” pakced vs unpacked
First Class Type Classes - Sozeau and Oury not canonical structures but it is in coq.
Unification Hints
Hints in unification Andrea Asperti, Wilmer Ricciotti, Claudio Sacerdoti Coen, and Enrico Tassi interesting paper. Describes how typeclasses and canonical structures can be put under a similar umbrella as extesnible unification mechanisms.
Diamonds
Coherence - typeclass systems can have diamonds
Diamonds are what are feared and dreaded. Why exacty?
trait coherence little orphan impls Overlapping - typeclass systems often take prolog style unification without backtracking, i.e. only one instance is allowed to apply. This is smart in the sense that it makes thge performance of the system simpler and more reliable, and performance here is compilation time for your users. It is of course also limitting
Overlapping
Instance Chains: Type Class Programming Without Overlapping Instances Non-overlapping means no heads are unifiable
non-overlapping means no backtracking. Can use egglog for unification then. Hmm. but head unification itself needs backtracking.
Multiparameter
Type-checking multi-parameter type classes 2002
Traits
To me it looks like a refactoring or multiparam typeclasses. Build syntatic rep of rust traits and then compiel to prology stuff from there. impl(Trait(A,B,C), T).
rustc guide common rust traits chalk book
Something to think about: Applications of egglog to typeclass resolution modulo equality. https://arxiv.org/abs/2001.04301 I don’t really have a feel for the relation between tabled top down and magic set transformed bottom up although there clearly is one. I guess I’m also not clear on how magic set works in egglog for that matter. I don’t know how to execute egglog top down in the first place. An example would be finding a typeclass for Vec n a where you take the assoc/comm mult and add axioms on the size index. Presumably the equational axioms must also be associated with instance dictionaries. Hmm. Maybe this is not as straightforward as I thought. You also need instances for congruence? There isn’t a problem with ordinary bottom up egglog, it just seems very wasteful on a query driven application like this
Chalk is also a very good point. The cahlk blog posts exliciitly talk about specialized equality. That is intriguing. I should contact Niko Matsakis. https://smallcultfollowing.com/babysteps/blog/2017/01/26/lowering-rust-traits-to-logic/ Prolog + euqliaty reasoning he syas he’s looking for
Chalk even talks about making a union find.
asscoaited types IntoIterator Item
intoiter(vec(T)) :- intoiter(T).
iter_item(vec(T)) = T :- intoiter(vec(T)).
eq(T,U)
query:
into_iter(vec(T))
Good examples of multi arg typeclasses?
Provenance of chalk or polonius are importatn for good error messages.
Guess missing clauses?
We need harrop for generic problems?
Functional Dependencies
Type Classes with Functional Dependencies? - Jones 2000
spj expression concern about fundeps
Understanding Functional Dependencies via Constraint Handling Rules - stuckey duck sulzmann spj
A general framework for hindley/milner type systems with constraints - sulzmann thesis HM(X)
stuckey sulzmann - a theory of overloading HM(X) + CHR
Associated Types
Associated Type Synonyms Associated Types with Class
Associated types are of some relationship to functional dependencies
Does class Foo a b c | a -> b, a -> c work like class Foo a where type b type c
Prolog
Typeclasses look like prolog predicates
instances are prolog rules. The proof of a successful resolution is a recipe for building the appropriate
Associated types means a piercing of this barrier
https://lpcic.github.io/coq-elpi/tutorial_elpi_lang.html
kind person type.
type fred, larry person.
pred daddy o:person, o:person.
daddy larry fred.
main :- daddy larry F, print F.
Build simply typed lambda checker. Add typeclases Oh, hmm. The mode annotations freeze it?
kind term type.
type app term -> term -> term.
type fun (term -> term) -> term.
kind ty type. % the data type of types
type arr ty -> ty -> ty. % our type constructor
pred whd i:term, o:term.
% when the head "Hd" of an "app" (lication) is a
% "fun" we substitute and continue
whd (app Hd Arg) Reduct :- whd Hd (fun F), !,
whd (F Arg) Reduct.
% otherwise a term X is already in normal form.
whd X Reduct :- Reduct = X.
pred of i:term, o:ty. % the type checking algorithm
% for the app node we ensure the head is a function from
% A to B, and that the argument is of type A
of (app Hd Arg) B :-
of Hd (arr A B), of Arg A.
% for lambda, instead of using a context (a list) of bound
% variables we use pi and => , explained below
of (fun F) (arr A B) :-
pi x\ of x A => of (F x) B.
kind class type.
% constr is =>
type constr class -> ty -> ty.
type eq ty -> class.
kind impl type.
pred instance i:class, o:impl.
type eq_impl term -> impl.
type bool ty.
type bool_eq term.
of bool_eq (arr bool (arr bool bool)).
type prod ty -> ty -> ty.
type pair term -> term -> term.
of (pair A B) (prod TA TB) :- of A TA, of B TB.
instance (eq bool) (eq_impl bool_eq).
% instance Eq a, Eq b => Eq (a,b) where ...
instance (eq (prod A B)) (eq_impl TODO) :- instance (eq A) (eq_impl ImplA), instance (eq B) (eq_impl ImplB).
datalog egglog
implements(clone,life(A,T))
impl(tostring, life(A,i64)).
impl(tostring, vec(T)) :- impl(tostring, T).
% associate what trait owns fields
traitfield(tostring, tostring).
dotcall( foo, tostring ) :- type(foo, T), traitfield(Trait, tostring), impl(Trant, T).
% dotcall(TEnv, foo, tostring)
% annotate everything with lifetimes?
% https://stevedonovan.github.io/rustifications/2018/09/08/common-rust-traits.html
% display, default, format, clone,
% sized
% borrow
% from to
% iterator
Original Wadler paper
Rust Chalk for Trait inference
BAP universal valures OCaml typeclasss system Oleg modellign typeclasses as prolog https://inbox.ocaml.org/caml-list/20190904152517.GA2014@Melchior.localnet/ http://okmij.org/ftp/ML/index.html#trep
So what is the synctatic condition that precludes search?
- nonoverlapping
Would it be more interesting to just What am I understanding here?
Canonical structures was suggesting that some kind of inconstency would manifest. Maybe lambda prolog gets us closer. We can have existential variables and such.
extensible unification
nat === (carrier nat_abGrp) :- A === A.
nat == carrier(Eq) :- Eq == natEq. carrier(Eq,nat).
nonunifiable(L) :- all( /= , L ).
% haskell has no backtracking % every case has a cut. eq(tup()) :- !. eq(tup(A,B)) :- !, eq(A), eq(B)
%
eq(int, prim__equal_int). eq(tup(A,B), lambda( x, case( x, tup(a,b) => bool_and( apply(EqualA, a) , apply(EqualB, b ) ) ) ) ) :- eq(A, EqualA), eq(B, EqualB). eq(tup(A,B), comp(and, par(EqualA,EqualB)))
eq(int). eq() eq(tup(A,B)) :- eq(A), eq(B).
ord(bool). ord().
functor( maybe ) functor(compose(F,G)) := functor(F), functor(G)
traversable :-
% superclass class(ord(A)) :- call(ord, A), class(eq(A))
“diamonds appear evertwhere. See pullbacks” ~ Hale