0

I have the following case. As can be seen, I have a less than class that takes ints and returns a bool. I am trying to create a Polyeq class that can take either ints or bools (or maybe even strings) and evaluates to see if they are equal and return a bool:

class Symantics repr where
    int :: Int  -> repr Int            
    add :: repr Int  -> repr Int -> repr Int
    bool :: Bool -> repr Bool

newtype R a = R{unR :: a}

instance Symantics R where
    int x     = R x
    add e1 e2 = R $ unR e1 + unR e2
    bool b    = R b

    
class Lth repr where
    lth :: repr Int -> repr Int -> repr Bool 

instance Lth R where
    lth e1 e2 = R $ unR e1 < unR e2  
    
 
class Polyeq a where
    polyeq :: a -> a -> Bool  
    
instance Polyeq R where
    polyeq e1 e2 = R $ unR e1 == unR e2  

I get the following error when compiling:

error:

• Couldn't match expected type ‘Bool’ with actual type ‘R Bool’

• In the expression: R $ unR e1 == unR e2

  In an equation for ‘polyeq’: polyeq e1 e2 = R $ unR e1 == unR e2

  In the instance declaration for ‘Polyeq Int’

error:

• Couldn't match expected type ‘R a0’ with actual type ‘Int’

• In the first argument of ‘unR’, namely ‘e1’

  In the first argument of ‘(==)’, namely ‘unR e1’

  In the second argument of ‘($)’, namely ‘unR e1 == unR e2’

error:

• Couldn't match expected type ‘R a0’ with actual type ‘Int’

• In the first argument of ‘unR’, namely ‘e2’

  In the second argument of ‘(==)’, namely ‘unR e2’

  In the second argument of ‘($)’, namely ‘unR e1 == unR e2’

Failed, modules loaded: none.

updated code: now throwing

error:

• Expecting one more argument to ‘R’

  Expected a type, but ‘R’ has kind ‘* -> *’

• In the first argument of ‘Polyeq’, namely ‘R’

  In the instance declaration for ‘Polyeq R’

Failed, modules loaded: none.

1 Answer 1

4

Your implementation of Polyeq R has two problems: first, its parameter R has the wrong kind (the class specifies *, but R has kind * -> *), and second the implementation of method polyeq returns R while its signature calls for Bool

The shortest way to fix is to provide the expected kind and expected implementation:

instance Polyeq (R a) where
    polyeq e1 e2 = unR e1 == unR e2  

But I suspect what you really meant was for the class to be defined on a variable of kind * -> *, similar to the Symantics class and its method add:

class Polyeq repr where
    polyeq :: Eq a => repr a -> repr a -> repr Bool  
    
instance Polyeq R where
    polyeq e1 e2 = R $ unR e1 == unR e2  

I must also note that customarily these things are achieved via an Applicative instance and liftA2.

If you define an Applicative instance for R:

instance Functor R where
    fmap f (R x) = R $ f x

instance Applicative R where
    pure = R
    liftA2 f (R a) (R b) = R $ f a b

Then all definitions in your classes degrade into:

int = pure
bool = pure
add = liftA2 (+)
lth = liftA2 (<)
polyeq = liftA2 (==)
Sign up to request clarification or add additional context in comments.

6 Comments

"But I suspect what you really meant was for the class to be defined on a variable of kind" Yes this is exactly what I was looking for.
In that case it really escapes me how you were able to define add, yet stumbled on polyeq
Can you please explain what Eq a => means. I am very new to haskell and functional programming
It means that whatever a turns out to be, it has to have an instance of the Eq class. That class is where the == function comes from, so you couldn't use it would such instance.
I see. If I wanted to create a polymorphic class that was not part of the Eq class, for example to find the first of a pair. Would it be: class Fst1 repr where fst1 :: repr a -> repr a -> repr a ---followed by--- instance Fst1 R where fst1 [x,x2] = R $ unR x ?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.