Reputation: 75
I'm having trouble with instance chaining in PureScript version 0.12.0-rc1
. The way I understand it, an instance chain allows one to specify instance resolution order explicitly to avoid instance definition overlapping.
I came up with the following example, but it won't compile:
class A a
class B b
class C c where
c :: c -> String
instance ca :: A a => C a where
c = const "ca"
else
instance cb :: B b => C b where
c = const "cb"
data X = X
instance bx :: B X
main :: forall eff. Eff (console :: CONSOLE | eff) Unit
main = logShow $ c X
What did I do wrong? Is my use of instance chaining incorrect?
Here's the full error message:
Error found:
in module Main
at src/Main.purs line 23, column 8 - line 23, column 20
No type class instance was found for
Main.A X
while applying a function c
of type C t0 => t0 -> String
to argument X
while inferring the type of c X
in value declaration main
where t0 is an unknown type
Upvotes: 3
Views: 455
Reputation: 2231
Even with instance chains matching is still done on the head of an instance. There is no "backtracking" when any of constraint fails for the chosen instance.
Your instances are completely overlapping on the head, so your first instance always matches before second one and it fails because there is no A
instance for X
.
Instance chains allows you to define explicit ordering of instance resolution without relying on for example alphabetical ordering of names etc. (as it was done till 0.12.0 version - please check the third paragraph here). For example you can define this overlapping scenario:
class IsRecord a where
isRecord :: a -> Boolean
instance a_isRecordRecord :: IsRecord (Record a) where
isRecord _ = true
instance b_isRecordOther :: IsRecord a where
isRecord _ = false
as
instance isRecordRecord :: IsRecord (Record a) where
isRecord _ = true
else instance isRecordOther :: IsRecord a where
isRecord _ = false
I hope it compiles - I don't have purs-0.12.0-rc
yet ;-)
Upvotes: 3