Haskell: using one class like another

I have code for the following circuit:

class First s where func1 :: s -> s class Second a where func2 :: s -> as data D s = D {value :: s} myFunc2 :: First s => s -> D s myFunc2 = undefined 

In the general argument, func2 cannot be an instance of First. I want to make an instance of D second only in cases where it computes an instance of First. Then I want to get this instance:

 instance Second D where func2 = myFunc2 

But I get an error message:

 No instance for (First s) arising from a use of `myFunc2' 

Ok, let the instance:

 instance First s => Second D where func2 = myFunc2 

But this gives an 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 an instance of a class with some conditions from other classes, but without all type variables after '=>'?

+4
source share
2 answers

I think it helps to think about what quality means.

 class Second a where func2 :: s -> as 

A Second instance promises, which func2 defined for any type s . But this does not apply to myFunc2 , because myFunc2 is defined only for those s for which an instance of First exists. This means that since you defined First and Second , it is not possible to use myFunc2 in an instance of Second (unless there is an instance of catch-all forall s . First s , but I suppose not, or you wouldn't bother to make a class).

So, you have to change at least one thing. You can override Second , as suggested by Grzegorz. If you don't like this, you can override Second as

 {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-} class Second as where func2 :: s -> as instance First s => Second D s where func2 = myFunc2 

Note that this says something other than what you originally wrote, because now the Second instance does not guarantee that func2 is polymorphic. But I think it’s closer to what you mean when you say, "make instance D of the second when it evaluates the instance of First." Perhaps this will be acceptable in your code.

+7
source

The exact solution will depend on what the code is trying to do, but the problem is that the type signature that you specify for func2 does not mention the First s constraint, while it needs an instance of func2 for Second D The following compilations:

 class First s where func1 :: s -> s class Second a where func2 :: First s => s -> as data D s = D {value :: s} myFunc2 :: First s => s -> D s myFunc2 = undefined instance Second D where func2 = myFunc2 
+6
source

Source: https://habr.com/ru/post/1401523/


All Articles