Philip Dorrell
Philip Dorrell

Reputation: 1658

In Idris, is "Eq a" a type, and can I supply a value for it?

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.

Upvotes: 6

Views: 581

Answers (1)

Belleve Invis
Belleve Invis

Reputation: 116

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...

Upvotes: 7

Related Questions