Haskell 复态单子结构

Haskell 复态单子结构,haskell,monads,state-monad,Haskell,Monads,State Monad,对哈斯克尔来说,我还是个新手,我想我现在已经不知所措了。我有如下代码 data World = World { intStack :: [Int], boolStack :: [Bool] } deriving Show instance IntStack World where getIntStack = intStack putIntStack ints (World _ bools) = World ints bools instance BoolStack Wor

对哈斯克尔来说,我还是个新手,我想我现在已经不知所措了。我有如下代码

data World = World {
  intStack :: [Int],
  boolStack :: [Bool]
} deriving Show

instance IntStack World where
   getIntStack = intStack
   putIntStack ints (World _ bools) = World ints bools

instance BoolStack World where
    getBoolStack = boolStack
    putBoolStack bools (World ints _) = World ints bools

class IntStack a where
    getIntStack :: a -> [Int]
    putIntStack :: [Int] -> a -> a

class BoolStack a where
    getBoolStack :: a -> [Bool]
    putBoolStack :: [Bool] -> a -> a

(<=>) :: (IntStack c, BoolStack c) => c -> c
(<=>) w = putIntStack xs . putBoolStack ((x == x'):bs) $ w
    where (x:x':xs) = getIntStack w
          bs = getBoolStack w

(<+>) :: (IntStack c) => c -> c
(<+>) w = putIntStack ((x+x'):xs) w
    where (x:x':xs) = getIntStack w
数据世界=世界{
intStack::[Int],
boolStack::[Bool]
}衍生节目
实例IntStack World在哪里
getIntStack=intStack
putIntStack ints(世界布尔)=世界整数布尔
实例BoolStack World在哪里
getBoolStack=boolStack
putBoolStack bools(世界整数)=世界整数bools
类INTA堆栈,其中
getIntStack::a->[Int]
putIntStack::[Int]->a->a
类布尔斯塔克a在哪里
getBoolStack::a->[Bool]
putBoolStack::[Bool]->a->a
():(IntStack c,BoolStack c)=>c->c
()w=putIntStack xs。putBoolStack((x==x'):bs)$w
其中(x:x):xs)=getIntStack w
bs=getBoolStack w
():(IntStack c)=>c->c
()w=putIntStack((x+x'):xs)w
其中(x:x):xs)=getIntStack w
我的重点(现在忽略函数中的错误情况)是能够将()和()之类的函数链接在一起,假设底层数据类型实现了函数所需的接口

我觉得我可以用一个状态单元组来清理这个问题,但我不知道如何构造它,以允许更改实现IntStack、BoolStack等的任何数据类型

我知道这是一个非常模糊的描述,但我觉得上面的代码可能是完全错误的


谢谢你的反馈

您可以在状态monad中实现push和pop操作,并使用它们实现您的功能:

popInt :: IntStack c => State c Int
popInt = do
  (x:xs) <- getIntStack <$> get
  modify $ putIntStack xs
  return x

pushInt :: IntStack c => Int -> State c ()
pushInt x = do
  xs <- getIntStack <$> get
  modify $ putIntStack (x:xs)

(<+>) :: IntStack c => State c ()
(<+>) = do 
  x <- popInt
  x' <- popInt
  pushInt (x + x')
popInt::IntStack c=>State c Int
popInt=do
(x:xs)Int->State c()
pushInt x=do
xs状态c()
做
x
恭喜你,你刚刚发明了隐形眼镜!对
[Int]
[Bool]
类型进行抽象,并使用
数据
而不是
,得到如下结果

data Lens a b = Lens
    { get :: a -> b
    , put :: b -> a -> a
    }
…这是在六个黑客软件包中实现的。大多数公司至少提供:

  • 能够直接从数据声明导出投影镜头,如
    getIntStack
    /
    putinstack
    getBoolStack
    /
    putBoolStack
  • 水平构图(先运行一个镜头,然后运行第二个镜头——例如,首先从某个较大的结构中选择一个
    世界
    ,然后从
    世界
    中选择
    intStack
    )和垂直构图(并行运行两个镜头,每一个都在一对的一侧)
  • 一些与
    State
    StateT
    的接口(例如
    lensab->statebr->statear
    类型的东西),可以让您在
    [Bool]
    [Int]
    上编写计算,并像在
    世界上运行计算一样运行它们

所以,看看黑客!还有
数据镜头
系列,包括和;一揽子计划;还有包裹。可能还有一些我也忘了。

耶,我还(重新)发明了镜头!我现在正在从黑客那里提取软件包+1非常感谢这一点,让我大吃一惊的是,这些东西是多么有用。
data Lens a b = Lens
    { get :: a -> b
    , put :: b -> a -> a
    }