Мне нужно преобразовать этот код C ++
class A {
public:
int x_A;
void setX_A (int newx) {
x_A = newx;
}
void printX_A() {
printf("x_A is %d", x_A);
}
};
class B : public A {
public:
int x_B;
void setX_B (int newx) {
x_B = newx;
}
void printX_B() {
printf("x_B is %d", x_B);
}
};
main() {
A objA;
B objB;
objA.setX_A(2);
objA.printX_A();
objB.printX_A();
objB.setX_B(5);
objB.printX_B();
}
в код Haskell и смоделировать main ()
, используя монаду State (или StateT).
Что я сделал для этого далеко это:
import Control.Monad.State
import Control.Monad.Identity
-- Fields For A
data FieldsA = FieldsA {x_A::Int} deriving (Show)
-- A Class Constructor
constA :: Int -> FieldsA
constA = FieldsA
class A a where
getX_A :: StateT a IO Int
setX_A :: Int -> StateT a IO ()
printX_A :: StateT a IO ()
instance A FieldsA where
getX_A = get >>= return . x_A
setX_A newx = do
fa <- get
put (fa { x_A = newx })
printX_A = do
fa <- get
liftIO $ print fa
return ()
data FieldsB = FieldsB{ fa::FieldsA, x_B::Int } deriving (Show)
constB :: Int -> Int -> FieldsB
constB int1 int2 = FieldsB {fa = constA int1, x_B = int2}
class A b => B b where
getX_B :: StateT b IO Int
setX_B :: Int -> StateT b IO ()
printX_B :: StateT b IO ()
-- A Functions for Class B
instance A FieldsB where
getX_A = do
(FieldsB (FieldsA x_A) x_B) <- get
return (x_A)
setX_A newx = do
(FieldsB (FieldsA x_A) x_B) <- get
put (constB newx x_B)
printX_A = do
fb <- get
liftIO $ print fb
return ()
-- B specific Functions
instance B FieldsB where
getX_B = get >>= return . x_B
setX_B newx = do
fb <- get
put (fb { x_B = newx })
printX_B = do
fb <- get
liftIO $ print fb
return ()
test :: StateT FieldsA (StateT FieldsB IO ) ()
test = do
x <- get
setX_A 4
printX_A
--lift $ setX_A 99
--lift $ setX_B 99
--lift $ printX_A
--lift $ printX_B
--printX_A
return ()
go = evalStateT (evalStateT test (constA 1)) (constB 2 3)
--go = runIdentity $ evalStateT (evalStateT test (constA 1)) (constA 1)
тест является main ()
.
Теперь о проблеме, которая у меня есть: когда я использую лифт, он работает нормально, потому что функция становится типа StateT
FieldsB
, но когда я пытаюсь использовать setX_A
без лифта, возникает проблема
*** Type : StateT FieldsA IO ()
*** Does not match : StateT FieldsA (StateT FieldsB IO) ()
Если я изменю тип setX_A
на второй, то он выиграет » t работает, когда я использую его с лифтом (потому что класс B является производным от A).