6

In the following, example1 is standard syntax (as documented), with Eq a as a constraint. In example2, I specify Eq a directly as the type of a parameter, and the compiler accepts it. However it is unclear what I can specify as a value of that type. For a specific type a, eg Nat, I assume it would make sense to somehow specify an implementation of Eq Nat, either the default implementation, or some other named implementation.

%default total

example1: Eq a => (x : a) -> (y : a) -> Type
example1 {a} x y = ?example1_rhs

example1b: Eq a => (x : a) -> (y : a) -> Type
example1b {a} x y = x == y = True

example2: (a : Type) -> Eq a -> (x : a) -> (y : a) -> Type
example2 a eqa x y = ?example2_rhs

example2b: (a : Type) -> Eq a -> (x : a) -> (y : a) -> Type
example2b a eqa x y = x == y = True

eq_nat : Eq Nat
eq_nat = ?eq_nat_rhs

example_of_example2 : Type
example_of_example2 = example2 Nat eq_nat 3 3

Resulting holes:

- + Main.example1_rhs [P]
 `--                  a : Type
                      x : a
                      y : a
             constraint : Eq a
     --------------------------
      Main.example1_rhs : Type

- + Main.example2_rhs [P]
 `--                  a : Type
                    eqa : Eq a
                      x : a
                      y : a
     --------------------------
      Main.example2_rhs : Type

- + Main.eq_nat_rhs [P]
 `-- Eq Nat

As far as I can tell, I can't actually use example2b as a function unless I have some way to specify a value for the second parameter of type Eq a.

There are situations where it would be genuinely useful to be able to apply an interface constraint to the value of a parameter (as opposed to the type of a parameter), so I'm hoping that this is a valid feature of Idris.

Anton Trunov
  • 15,074
  • 2
  • 23
  • 43
Philip Dorrell
  • 1,658
  • 11
  • 15
  • It occurred to me that I forgot to do a proof search on the `?eq_nat_rhs` hole. When I did so, it returned `Nat implementation of Prelude.Interfaces.Eq`. This makes sense, but unfortunately it is not valid Idris code, and it doesn't compile. – Philip Dorrell Jun 03 '17 at 03:36

1 Answers1

7

You could use named implementations:

[eq_nat] Eq Nat where { ... }
...
example_of_example2 : Type
example_of_example2 = example2 Nat eq_nat 3 3

A useful application of named implementations are defining multiple implementation of Monoid:

[PlusNatSemi] Semigroup Nat where
  (<+>) x y = x + y

[MultNatSemi] Semigroup Nat where
  (<+>) x y = x * y

[PlusNatMonoid] Monoid Nat using PlusNatSemi where
  neutral = 0

[MultNatMonoid] Monoid Nat using MultNatSemi where
  neutral = 1

To comment : To get the default instance

getEq : (a : Type) -> {auto inst : Eq a} -> Eq a
getEq a {inst} = inst

Then you can have your default instance:

getEq (List Nat) -- => implementation of Eq...
Anton Trunov
  • 15,074
  • 2
  • 23
  • 43
  • 1
    So if I define a named implementation, then that name references the "thing" which is of type `Eq a`. Consequent questions are: (1) Should this be documented? (I see nothing in http://docs.idris-lang.org/en/latest/tutorial/interfaces.html), and (2) is there any way to refer to the default implementation of an interface (ie does it have a name)? – Philip Dorrell Jun 03 '17 at 22:11