I have a code to the following scheme:
class First s where
func1 :: s -> s
class Second a where
func2 :: s -> a s
data D s = D {value :: s}
myFunc2 :: First s => s -> D s
myFunc2 = undefined
In common func2’s argument could not be instance of First. I want to make D instance of Second in only that cases when it’s value instance of First.
Then I want to get this instance:
instance Second D where
func2 = myFunc2
But I get an error:
No instance for (First s)
arising from a use of `myFunc2'
Okay, let instance be:
instance First s => Second D where
func2 = myFunc2
But this gives error:
Ambiguous constraint `First s'
At least one of the forall'd type variables mentioned by the constraint
must be reachable from the type after the '=>'
In the instance declaration for `Second D'
So, is there a way to get instance of class with some conditions from other classes, but without all type variables after ‘=>’?
I think it helps to think about what is meant qualitatively by
A
Secondinstance promises thatfunc2is defined for any types. But that’s not true ofmyFunc2, becausemyFunc2is only defined for thosesfor which there exists aFirstinstance. This means that as you have definedFirstandSecond, it is not possible to usemyFunc2in aSecondinstance (unless there existed a catch-allforall s . First sinstance, but I’m assuming not, or you wouldn’t have bothered to make a typeclass).So, you will have to change at least one thing. You could redefine
Secondas Grzegorz suggested. If you don’t like that, you could redefineSecondlikeNote that this is saying something different than what you wrote originally, because now a
Secondinstance does not guarantee thatfunc2is polymorphic. But I think this is closer to what you mean when you say “make D instance of Second in only that cases when it’s value instance of First”. Maybe it will be acceptable in your code.