Haskell Control.Monad.State API最近有变化吗?
作为一个学习练习,我试图在Haskell中实现heapsort。我认为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
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)
从读取forControl.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
块中直接排序的一元函数吗?