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:
- I need to separate this two module.
- As possible as I can, I do not want to use hs-boot, but more elegant way
winupdate :: a -> w -> IO wand thewininstance Manage (T w)are completely unrelated. You probably want something likeclass Manage a w | a -> w where update :: a -> w -> IO wandinstance Manage (T w) w. Or possiblyclass Manage a where update :: a w -> w -> IO w.ws are not related, but I had no way. The first of your answer works. However,the second one makes error likeThe first argument of ‘Manage’ should have kind ‘* -> *’, but ‘T w’ has kind ‘*’. It seems to be better then the first one, but...instance Manage T, notinstance Manage (T w).