0

At first, I tried to solve mutual recursive module problem. However, my effort to solve this problem makes the code worse.

Original problem

I have two module like

module W where

import T

data W = W  { wName  :: String
            , queue  :: [T W]}`

and

module T where

import W

data T = T { tName  :: String
            , tUpdate :: W -> IO W}

class Manage a where
    update :: a -> W -> IO W

instance Manage T where
    update = tUpdate

These modules are not able to work, because of mutual recursive modules problem.

So I changed module T, according to this link

New solution with data variable

module T where

data T w = T { tName  :: String
            , tUpdate :: w -> IO w}

class Manage a where
    update :: a -> w -> IO w

instance Manage (T w) where
    update = tUpdate

However, this code makes error like:

Couldn't match type ‘w’ with ‘w1’
  ‘w’ is a rigid type variable bound by
      the instance declaration at TestModule2.hs:12:10
  ‘w1’ is a rigid type variable bound by
       the type signature for update :: T w -> w1 -> IO w1
       at TestModule2.hs:13:5
Expected type: T w -> w1 -> IO w1
  Actual type: T w -> w -> IO w
Relevant bindings include
  update :: T w -> w1 -> IO w1 (bound at TestModule2.hs:13:5)
In the expression: tUpdate
In an equation for ‘update’: update = tUpdate

So, I tried many things to solve this problem like

Introduce new class like State w to represent data W

To solve rigid type variable ..., I introduced new class.

{-# LANGUAGE InstanceSigs, Rank2Types #-}
module T where

.....

data T w = T  { tName  :: String
              , tUpdate :: (State w) => w -> IO w}

class Manage a where
    update :: (State w) => a -> (w -> IO w)

instance (State w) => Manage (T w) where
    update :: T w -> w -> IO w
    update = tUpdate

But this code also makes error like:

Method signature does not match class; it should be
  update :: forall w1. State w1 => T w -> w1 -> IO w1
In the instance declaration for ‘Manage (T w)’

I followed this suggestion, but this doesn't work. Moreover, w1 and w should be same type.

Do I need to define class or class method other way?

So, What do I need to study and how could I solve this problem?

I tried more things, but I couldn't solve this. What do I need to study to solve this problem? And how could I solve this problem?

Important points:

  1. I need to separate this two module.
  2. As possible as I can, I do not want to use hs-boot, but more elegant way
3
  • 1
    This has nothing to do with modules. The w in update :: a -> w -> IO w and the w in instance Manage (T w) are completely unrelated. You probably want something like class Manage a w | a -> w where update :: a -> w -> IO w and instance Manage (T w) w. Or possibly class Manage a where update :: a w -> w -> IO w. Commented Mar 19, 2015 at 4:43
  • Thanks for your help. I knew that ws are not related, but I had no way. The first of your answer works. However,the second one makes error like The first argument of ‘Manage’ should have kind ‘* -> *’, but ‘T w’ has kind ‘*’. It seems to be better then the first one, but... Commented Mar 19, 2015 at 5:00
  • If you use the 2nd suggestion, it will be instance Manage T, not instance Manage (T w). Commented Mar 19, 2015 at 5:07

1 Answer 1

1

Based on user2407038 comments, one solution can be :

Module T:

module T where

data T w = T { tName   :: String
             , tUpdate :: w -> IO w
             }

class Manage a where
    update :: a w -> w -> IO w

instance Manage T where
    update = tUpdate

Module W:

module W where

import T

data W = W { wName :: String
           , queue :: [T W]
           }
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks zigazou, user2407038 a lot. These answers are very helpful for me.

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.