Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Juvix Type classes #1646

Closed
jonaprieto opened this issue Nov 22, 2022 · 1 comment · Fixed by #2320
Closed

Juvix Type classes #1646

jonaprieto opened this issue Nov 22, 2022 · 1 comment · Fixed by #2320
Assignees
Milestone

Comments

@jonaprieto
Copy link
Collaborator

jonaprieto commented Nov 22, 2022

We want to use type classes as follows:

class
type SemiGroup (A : Type) :=
  mkSemiGroup {
    comp : A -> A -> A;
  };

For declaring instances, use the following syntax:

instance
f : {A : Type} -> SemiGroup (List a);
f := mkSemiGroup {comp := List.comp };

use cases:

g : {A : Type} -> List A -> List A -> List A ;
g l1 l2 := comp l1 l2;

h : {A : Type} -> {{SemiGroup A}} -> A -> A;
h {{M}} a := comp {{M}} a a; -- {{M}} is not necessary. 

See the following papers:

@jonaprieto jonaprieto added this to the 0.4 milestone Nov 22, 2022
@lukaszcz lukaszcz modified the milestones: 0.6, 0.5 Jan 23, 2023
@lukaszcz
Copy link
Collaborator

lukaszcz commented Apr 7, 2023

I propose to call these traits and use trait instead of class, for two reasons:

  1. Rust (and partly Scala) call them traits.
  2. In my experience teaching Haskell, regardless of how much you explain this, people think that class has something to do with classes in Java and try do object-oriented programming with type classes, sometimes in ridiculously inventive and elaborate ways.

@lukaszcz lukaszcz modified the milestones: 0.5 , 0.4.1 Jun 22, 2023
@paulcadman paulcadman modified the milestones: 0.4.1, 0.4.2 Jun 23, 2023
@lukaszcz lukaszcz modified the milestones: 0.4.2, 0.5 Jun 27, 2023
@lukaszcz lukaszcz self-assigned this Aug 28, 2023
@lukaszcz lukaszcz mentioned this issue Aug 28, 2023
lukaszcz added a commit that referenced this issue Sep 8, 2023
* Closes #1646 

Implements a basic trait framework. A simple instance search mechanism
is included which fails if there is more than one matching instance at
any step.

Example usage:
```
import Stdlib.Prelude open hiding {Show; mkShow; show};

trait
type Show A :=
  mkShow {
    show : A → String
  };

instance
showStringI : Show String := mkShow (show := id);

instance
showBoolI : Show Bool := mkShow (show := λ{x := if x "true" "false"});

instance
showNatI : Show Nat := mkShow (show := natToString);

showList {A} : {{Show A}} → List A → String
  | nil := "nil"
  | (h :: t) := Show.show h ++str " :: " ++str showList t;

instance
showListI {A} {{Show A}} : Show (List A) := mkShow (show := showList);

showMaybe {A} {{Show A}} : Maybe A → String
  | (just x) := "just (" ++str Show.show x ++str ")"
  | nothing := "nothing";

instance
showMaybeI {A} {{Show A}} : Show (Maybe A) := mkShow (show := showMaybe);

main : IO :=
  printStringLn (Show.show true) >>
  printStringLn (Show.show false) >>
  printStringLn (Show.show 3) >>
  printStringLn (Show.show [true; false]) >>
  printStringLn (Show.show [1; 2; 3]) >>
  printStringLn (Show.show [1; 2]) >>
  printStringLn (Show.show [true; false]) >>
  printStringLn (Show.show [just true; nothing; just false]) >>
  printStringLn (Show.show [just [1]; nothing; just [2; 3]]) >>
  printStringLn (Show.show "abba") >>
  printStringLn (Show.show ["a"; "b"; "c"; "d"]);
```

It is possible to manually provide an instance and to match on implicit
instances:
```
f {A} : {{Show A}} -> A -> String
  | {{mkShow s}} x -> s x;

f' {A} : {{Show A}} → A → String
  | {{M}} x := Show.show {{M}} x;
```

The trait parameters in instance types are checked to be structurally
decreasing to avoid looping in the instance search. So the following is
rejected:
```
type Box A := box A;

trait
type T A := mkT { pp : A → A };

instance
boxT {A} : {{T (Box A)}} → T (Box A) := mkT (λ{x := x});
```
We check whether each parameter is a strict subterm of some trait
parameter in the target. This ordering is included in the finite
multiset extension of the subterm ordering, hence terminating.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants