Haskell Control.Monad.State API最近有变化吗?

Haskell Control.Monad.State API最近有变化吗?,haskell,state-monad,Haskell,State Monad,作为一个学习练习,我试图在Haskell中实现heapsort。我认为Statemonad是正确的选择,因为堆在很大程度上依赖于在单个结构中移动数据(并且do表示法将非常有用)。此外,我希望巩固我对单子的理解 在了解Haskell(和of)中,表示状态定义为: newtype State s a = State { runState :: s -> (a,s) } 我应该将s->(a,s)类型的函数(可能在其他参数中出现,也可能不出现)传递给状态值构造函数。因此,我的函数如下所示: po

作为一个学习练习,我试图在Haskell中实现heapsort。我认为
State
monad是正确的选择,因为堆在很大程度上依赖于在单个结构中移动数据(并且
do
表示法将非常有用)。此外,我希望巩固我对单子的理解

在了解Haskell(和of)中,表示
状态
定义为:

newtype State s a = State { runState :: s -> (a,s) }
我应该将
s->(a,s)
类型的函数(可能在其他参数中出现,也可能不出现)传递给
状态
值构造函数。因此,我的函数如下所示:

pop :: Ord a => State (Heap a) a
pop = State pop'
pop' :: Ord a => Heap a -> (a, Heap a)
-- implementation of pop' goes here

push :: Ord a => a -> State (Heap a) ()
push item = State $ push' item
push' :: Ord a => a -> Heap a -> ((), Heap a)
-- implementation of push' goes here
这不会编译,出现以下错误:

Not in scope: data constructor `State'
Perhaps you meant `StateT' (imported from Control.Monad.State)
从读取for
Control.Monad.State
中,似乎自编写这些教程以来,
State
值构造函数已从模块中删除。作为一名初学者,我发现这些文档远非易懂。所以我的问题是:

  • 我认为
    状态
    值构造函数消失了,这对吗
  • 我应该用什么来代替
  • 是的,它不见了,取而代之的是。(现在根据
    StateT
    monad转换器定义了
    State
    monad。)
  • 您应该改为使用该函数

  • 然而,我怀疑你的方法是否正确。而不必担心<代码>状态< /代码>是如何实现的,请考虑使用DO符号和<代码>获取< /COD>和<代码>放置< /代码>函数。

    < P>这里是有关状态单元格的示例中的正确实现:

    一元堆栈:

    -- MonadicStack.hs (Learn You a Haskell for Great Good!)
    
    import Control.Monad.State  
    
    type Stack = [Int]
    
    pop :: State Stack Int
    -- The following line was wrong in the book:
    -- pop = State $ \(x:xs) -> (x,xs)  
    pop = do
     x:xs <- get
     put xs
     return x
    
    push :: Int -> State Stack ()  
    -- The following line was wrong in the book:
    -- push a = State $ \xs -> ((),a:xs)
    push a = do
     xs <- get
     put (a:xs)
     return ()
    
    pop1 = runState pop [1..5]
    push1 = runState (push 1) [2..5]
    
    stackManip :: State Stack Int  
    stackManip = do  
     push 3  
     a <- pop  
     pop  
    
    stackManip1 = runState stackManip [5,8,2,1]  
    stackManip2 = runState stackManip [1,2,3,4]  
    
    stackStuff :: State Stack ()  
    stackStuff = do  
     a <- pop  
     if a == 5  
      then push 5  
      else do  
       push 3  
       push 8  
    
    stackStuff1 = runState stackStuff [9,0,2,1,0]  
    stackStuff2 = runState stackStuff [5,4,3,2,1]
    
    moreStack :: State Stack ()  
    moreStack = do  
     a <- stackManip  
     if a == 100  
      then stackStuff  
      else return ()  
    
    moreStack1 = runState moreStack [100,9,0,2,1,0]
    moreStack2 = runState moreStack [9,0,2,1,0]
    
    stackyStack :: State Stack ()  
    stackyStack = do  
     stackNow <- get  
     if stackNow == [1,2,3]  
      then put [8,3,1]  
      else put [9,2,1]  
    
    stackyStack1 = runState stackyStack [1,2,3]
    stackyStack2 = runState stackyStack [10,20,30,40]
    
    -- DesugaredMonadicStack.hs (Learn You a Haskell for Great Good!)
    
    import Control.Monad.State  
    
    type Stack = [Int]
    
    pop :: State Stack Int  
    pop = 
     get >>=
     \(x:xs) -> put xs >>
     return x
    
    push :: Int -> State Stack ()
    push a =
     get >>=
     \xs -> put (a:xs) >>
     return ()
    
    pop1 = runState pop [1..5]
    push1 = runState (push 1) [2..5]
    
    stackManip :: State Stack Int  
    stackManip =
     push 3 >>
     pop >>=
     \a -> pop
    
    stackManip1 = runState stackManip [5,8,2,1]  
    stackManip2 = runState stackManip [1,2,3,4]  
    
    stackStuff :: State Stack ()  
    stackStuff =
     pop >>=
     \a -> 
      if a == 5 then
       push 5
      else
       push 3 >>
       push 8
    
    stackStuff1 = runState stackStuff [9,0,2,1,0]  
    stackStuff2 = runState stackStuff [5,4,3,2,1]
    
    moreStack :: State Stack ()  
    moreStack =
     stackManip >>=
     \a ->
      if a == 100 then
       stackStuff
      else
       return ()
    
    moreStack1 = runState moreStack [100,9,0,2,1,0]
    moreStack2 = runState moreStack [9,0,2,1,0]
    moreStack3 = runState moreStack [100,5,4,3,2,1]
    
    stackyStack :: State Stack ()  
    stackyStack =
     get >>=
     \stackNow ->
      if stackNow == [1,2,3] then
       put [8,3,1]
      else
       put [9,2,1]
    
    stackyStack1 = runState stackyStack [1,2,3]
    stackyStack2 = runState stackyStack [10,20,30,40] 
    
    --MonadicStack.hs(学习Haskell对你有好处!)
    进口控制单体状态
    类型Stack=[Int]
    状态堆栈Int
    --书中的以下行是错误的:
    --pop=状态$\(x:xs)->(x,xs)
    pop=do
    x:xs状态堆栈()
    --书中的以下行是错误的:
    --推送a=State$\xs->((),a:xs)
    按a=do
    
    xs我认为
    state
    有助于
    pop
    的简洁实现,但是
    modify
    更适合
    push
    ,因为它返回单位:

    import Control.Monad.State  
    
    type Stack a = [a]
    
    pop :: State (Stack a) a
    pop = state $ \(a:as) -> (a, as)
    
    push :: a -> State (Stack a) ()  
    push a = modify (a:)
    

    脱糖单体堆栈:

    -- MonadicStack.hs (Learn You a Haskell for Great Good!)
    
    import Control.Monad.State  
    
    type Stack = [Int]
    
    pop :: State Stack Int
    -- The following line was wrong in the book:
    -- pop = State $ \(x:xs) -> (x,xs)  
    pop = do
     x:xs <- get
     put xs
     return x
    
    push :: Int -> State Stack ()  
    -- The following line was wrong in the book:
    -- push a = State $ \xs -> ((),a:xs)
    push a = do
     xs <- get
     put (a:xs)
     return ()
    
    pop1 = runState pop [1..5]
    push1 = runState (push 1) [2..5]
    
    stackManip :: State Stack Int  
    stackManip = do  
     push 3  
     a <- pop  
     pop  
    
    stackManip1 = runState stackManip [5,8,2,1]  
    stackManip2 = runState stackManip [1,2,3,4]  
    
    stackStuff :: State Stack ()  
    stackStuff = do  
     a <- pop  
     if a == 5  
      then push 5  
      else do  
       push 3  
       push 8  
    
    stackStuff1 = runState stackStuff [9,0,2,1,0]  
    stackStuff2 = runState stackStuff [5,4,3,2,1]
    
    moreStack :: State Stack ()  
    moreStack = do  
     a <- stackManip  
     if a == 100  
      then stackStuff  
      else return ()  
    
    moreStack1 = runState moreStack [100,9,0,2,1,0]
    moreStack2 = runState moreStack [9,0,2,1,0]
    
    stackyStack :: State Stack ()  
    stackyStack = do  
     stackNow <- get  
     if stackNow == [1,2,3]  
      then put [8,3,1]  
      else put [9,2,1]  
    
    stackyStack1 = runState stackyStack [1,2,3]
    stackyStack2 = runState stackyStack [10,20,30,40]
    
    -- DesugaredMonadicStack.hs (Learn You a Haskell for Great Good!)
    
    import Control.Monad.State  
    
    type Stack = [Int]
    
    pop :: State Stack Int  
    pop = 
     get >>=
     \(x:xs) -> put xs >>
     return x
    
    push :: Int -> State Stack ()
    push a =
     get >>=
     \xs -> put (a:xs) >>
     return ()
    
    pop1 = runState pop [1..5]
    push1 = runState (push 1) [2..5]
    
    stackManip :: State Stack Int  
    stackManip =
     push 3 >>
     pop >>=
     \a -> pop
    
    stackManip1 = runState stackManip [5,8,2,1]  
    stackManip2 = runState stackManip [1,2,3,4]  
    
    stackStuff :: State Stack ()  
    stackStuff =
     pop >>=
     \a -> 
      if a == 5 then
       push 5
      else
       push 3 >>
       push 8
    
    stackStuff1 = runState stackStuff [9,0,2,1,0]  
    stackStuff2 = runState stackStuff [5,4,3,2,1]
    
    moreStack :: State Stack ()  
    moreStack =
     stackManip >>=
     \a ->
      if a == 100 then
       stackStuff
      else
       return ()
    
    moreStack1 = runState moreStack [100,9,0,2,1,0]
    moreStack2 = runState moreStack [9,0,2,1,0]
    moreStack3 = runState moreStack [100,5,4,3,2,1]
    
    stackyStack :: State Stack ()  
    stackyStack =
     get >>=
     \stackNow ->
      if stackNow == [1,2,3] then
       put [8,3,1]
      else
       put [9,2,1]
    
    stackyStack1 = runState stackyStack [1,2,3]
    stackyStack2 = runState stackyStack [10,20,30,40] 
    
    去糖单元随机发生器:

    -- DesugaredMonadicRandomGenerator.hs (Learn You a Haskell for Great Good!)
    
    import System.Random  
    import Control.Monad.State  
    
    randomSt :: (RandomGen g, Random a) => State g a  
    randomSt =
     get >>=
     \gen -> 
      let (value,nextGen) = random gen
      in
       put nextGen >>
       return value
    
    randomSt1 = (runState randomSt (mkStdGen 1)) :: (Int,StdGen)
    randomSt2 = (runState randomSt (mkStdGen 2)) :: (Float,StdGen)
    
    threeCoins :: State StdGen (Bool,Bool,Bool)
    threeCoins =
     randomSt >>=
     \a -> randomSt >>=
     \b -> randomSt >>=
     \c -> return (a,b,c)
    
    threeCoins1 = runState threeCoins (mkStdGen 33)
    threeCoins2 = runState threeCoins (mkStdGen 2)
    
    -- rollDie and rollNDice are not explained in the book LYAHFGG. 
    -- But these functions are interesting and complementary:
    
    rollDie :: State StdGen Int
    rollDie =
     get >>=
     \generator -> 
      let (value, newGenerator) = randomR (1,6) generator
      in
       put newGenerator >>
       return value
    
    rollDie1 = runState rollDie (mkStdGen 1)
    rollDie2 = runState rollDie (mkStdGen 2)
    
    rollNDice :: Int -> State StdGen [Int]
    rollNDice 0 = return []
    rollNDice n =
     rollDie >>=
     \value -> rollNDice (n-1) >>=
     \list -> return (value:list)
    
    rollNDice1 = runState (rollNDice 10) (mkStdGen 1)
    rollNDice2 = runState (rollNDice 20) (mkStdGen 2) 
    

    state
    是否是
    state
    的替代品?或者我需要为我的数据结构声明一个
    MonadState
    实例,然后它才能工作吗?
    state
    state
    的替代品,是的
    State(Heap a)
    是MonadState
    的一个实例,并且已经是了。您建议使用
    do
    符号和
    get
    put
    的推荐样式是什么?我是否应该非一元地定义大多数低级函数(例如:
    push::Ord a=>a->Heap a->Heap a
    ),然后使用大量的
    let
    绑定在
    do
    块中用这些函数构建一个有状态计算?或者
    push
    pop
    (或者,在较低的级别上,我的树遍历例程)应该是可以在
    do
    块中直接排序的一元函数吗?