Ben*_*son 14 haskell state-monad
作为一个学习练习,我试图在Haskell中实现一个heapsort.我认为State
monad将是这样做的正确选择,因为堆积很大程度上依赖于在单个结构内部移动数据(并且do
符号将是有用的).此外,我希望能够巩固我对monad的理解.
在这些示例State
单子在了解你的Haskell(和数量的其他 教程),说的是State
被定义为:
newtype State s a = State { runState :: s -> (a,s) }
Run Code Online (Sandbox Code Playgroud)
我应该将类型的函数s -> (a,s)
(可能在其他参数中,也可能不在其他参数中)传递给State
值构造函数.所以我的函数看起来像这样:
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
Run Code Online (Sandbox Code Playgroud)
这不会编译,出现以下错误:
Not in scope: data constructor `State'
Perhaps you meant `StateT' (imported from Control.Monad.State)
Run Code Online (Sandbox Code Playgroud)
从阅读API文档的Control.Monad.State
,它看起来好像State
值构造已经从模块中去掉,因为这些教程写.作为初学者,我发现文档远非不言自明.所以我的问题是:
State
价值构造者已经消失了?Jua*_*nto 13
以下是与State Monad相关的书中显示的示例的正确实现:
MONADIC STACK:
-- 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]
Run Code Online (Sandbox Code Playgroud)
MONADIC随机发生器:
-- MonadicRandomGenerator.hs (Learn You a Haskell for Great Good!)
import System.Random
import Control.Monad.State
randomSt :: (RandomGen g, Random a) => State g a
-- The following line was wrong in the book:
-- randomSt = State random
randomSt = do
gen <- get
let (value,nextGen) = random gen
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 = do
a <- randomSt
b <- randomSt
c <- randomSt
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 = do
generator <- get
let (value, newGenerator) = randomR (1,6) generator
put newGenerator
return value
rollDie1 = runState rollDie (mkStdGen 1)
rollDie2 = runState rollDie (mkStdGen 2)
rollNDice :: Int -> State StdGen [Int]
rollNDice 0 = do
return []
rollNDice n = do
value <- rollDie
list <- rollNDice (n-1)
return (value:list)
rollNDice1 = runState (rollNDice 10) (mkStdGen 1)
rollNDice2 = runState (rollNDice 20) (mkStdGen 2)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2892 次 |
最近记录: |