Kevin Meredith
Kevin Meredith

Reputation: 41909

Define Equality of Lists Function

Type-Driven Development with Idris presents this exercise:

same_cons : {xs : List a} -> {ys : List a} -> xs = ys -> x :: xs = x :: ys

However, I attempted to implement it via:

data EqList : (xs : List a) -> (ys : List a) -> Type where
   Same : (xs: List a) -> EqList xs xs

sameS : (xs : List a) -> (ys : List a) -> (x: a) -> (eq : EqList xs ys) -> EqList (x :: xs) (x :: ys)
sameS xs xs x (Same xs) = Same (x :: xs)

same_cons : {xs : List a} -> {ys : List a} -> (eq : EqList xs ys) -> EqList (x :: xs) (x :: ys)
same_cons {xs} {ys} eq = sameS xs ys _ eq

I inferred the x in EqList (x :: xs) (x :: ys) because I'm confused how to get an x if xs and ys are empty.

Also, the above compiles, but it failed when I tried to call it:

*Exercises> same_cons (Same [1,2,3])
(input):Can't infer argument x to same_cons

Upvotes: 0

Views: 131

Answers (2)

xash
xash

Reputation: 3722

To clarify on how to get the x: Everything in lowercase in the type decleration will become an implicit argument, if it isn't already explicit. So

same_cons : {xs : List a} -> {ys : List a} ->
            (eq : EqList xs ys) -> EqList (x :: xs) (x :: ys)

is the same as

same_cons : {a : Type} -> {x : a} -> {xs : List a} -> {ys : List a} -> 
            (eq : EqList xs ys) -> EqList (x :: xs) (x :: ys)

That's where the x is hiding. So you could use {x} on the left hand side of the definition to get it. Or just let Idris handle all the stuff and use Cactus' definition. For future problems with arguments, you can use :set showimplicits in the REPL to show you all the implicit arguments when asking for types, e.g. :t same_cons.

And when Idris cannot infer the value for an implicit argument, you can help it by giving the resulting type like Cactus did or set the implicit argument to a value:

*> same_cons {x=0} (Same [3,2,5])
Same [0, 3, 2, 5] : EqList [0, 3, 2, 5] [0, 3, 2, 5]

Upvotes: 2

Cactus
Cactus

Reputation: 27626

The implicit argument x cannot be inferred in your use case because there is no information in the call same_cons (Same [1,2,3]) to constrain it to anything. If you fix the type of the result, that will give you the choice of x, e.g.

λΠ> the (EqList [0,1,2,3] [0,1,2,3]) (same_cons (Same [1,2,3]))
Same [0, 1, 2, 3] : EqList [0, 1, 2, 3] [0, 1, 2, 3]

since the choice of [0,1,2,3] for x:xs unifies x with 0.

BTW you can simplify the definition of same_cons since the eq argument's type determines xs and ys so you can let Idris infer it:

same_cons : (eq : EqList xs ys) -> EqList (x :: xs) (x :: ys)
same_cons eq = sameS _ _ _ eq

Upvotes: 2

Related Questions