3

I want to recursively collect arguments of a function to a tuple with nesting (the general idea is taken from here).

I have a class with a function with polymorphic parameter (a, b). I want to make an instance for this class so that its parameters should be the same a and b:

class MyClass r where
    my_fun :: (a, b) -> r

instance MyClass (a, b) where
    my_fun x = x -- problematic place

instance MyClass r => MyClass (s -> r) where
    my_fun (a,b) s = my_fun (ff (a,b) s)

ff :: (a,b) -> s -> ((a,b), s)
ff x s = (x, s)

But I get a compilation error:

    * Couldn't match type `a1' with `a'
      Expected: (a, b)
        Actual: (a1, b1)
      `a1' is a rigid type variable bound by
        the type signature for:
          my_fun :: forall a1 b1. (a1, b1) -> (a, b)
        at class.hs:5:5-10
      `a' is a rigid type variable bound by
        the instance declaration
        at class.hs:4:10-23

How can I instruct the compiler that a and b in the instance are the same as in function declaration?

6
  • Give some more context for what you're trying to accomplish here. It doesn't really make sense to do that as you've asked. How do you intend to use myFun? Commented Oct 8 at 15:14
  • I want to recursively collect arguments of the function to a tuple with nesting class MyClass r where my_fun :: (a, b) -> r instance MyClass (a, b) where my_fun x = x -- problematic place instance MyClass r => MyClass (s -> r) where my_fun (a,b) s = my_fun (ff (a,b) s) ff :: (a,b) -> s -> ((a,b), s) ff x s = (x, s) Commented Oct 8 at 15:38
  • I've got this idea here Commented Oct 8 at 15:45
  • 1
    Edit this context into your question. Commented Oct 8 at 16:10
  • @NaïmCamilleFavier Done. However, I'd like to get an answer not only because of this particular goal. I'd like to improve my general understanding of Haskell. Commented Oct 8 at 17:11

1 Answer 1

2

The simplest approach is just to add the parameters to the class:

{-# LANGUAGE UndecidableInstances #-}

class MyClass a b r where
    my_fun :: (a, b) -> r

instance MyClass a b (a, b) where
    my_fun x = x

instance MyClass (a, b) s r => MyClass a b (s -> r) where
    my_fun (a,b) s = my_fun (ff (a,b) s)

ff :: (a,b) -> s -> ((a,b), s)
ff x s = (x, s)

(Don't worry too much about the undecidable instances extension, the default decidability checker is overly restrictive. The worst thing that can happen is that the compiler getting stuck in an infinite loop when trying to compile your program.)

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. Indeed, this is a good solution.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.