[英]Using Maybe with State Monad
我正在嘗試使用push / pop / peek操作在Haskell中實現FIFO隊列,這是我到目前為止所做的。
data Queue a = Queue {
inbox :: [a],
outbox :: [a]
} deriving (Eq, Show)
push :: a -> Queue a -> Queue a
push e (Queue inb out) = Queue (e:inb) out
pop :: Queue a -> (Maybe a, Queue a)
pop q =
case top of
Nothing -> (top, emptyQueue)
Just elem -> (Just elem, poppedQueue)
where
(top, q') = peek q
poppedQueue = Queue (inbox q') (tail $ outbox q')
peek :: Queue a -> (Maybe a, Queue a)
peek q@(Queue [] []) = (Nothing, emptyQueue)
peek q@(Queue inb []) = peek $ Queue [] (reverse inb)
peek q@(Queue _ outb) = (Just $ head outb, q)
emptyQueue = Queue [] []
所以上面的工作,我可以推/我/我的隊列。 如你所見,我將一個返回類型包含在一個Maybe中,這樣如果我彈出一個空隊列或者查看一個空隊列,我就得到一個Nothing,否則就是Just元素。
所以我也認為我可以使用State monad輕松連接操作。 我進行如下:
type QueueState a = State (Queue a)
pushQueue :: a -> QueueState a ()
pushQueue e = state $ \q -> ((),push e q)
popQueue :: QueueState a (Maybe a)
popQueue = state $ \q -> pop q
好吧,所以這似乎工作。 我可以:
runState (pushQueue 2 >> pushQueue 3 >> popQueue >> pushQueue 1 >> popQueue) emptyQueue
然后回來(Just 3,Queue {inbox = [1], outbox = []})
,這就是我想要的。 但我做不了類似的事情:
runState (pushQueue 2 >> popQueue >>= pushQueue) emptyQueue
這導致:
Occurs check: cannot construct the infinite type: a0 = Maybe a0
Expected type: Maybe a0
-> StateT (Queue a0) Data.Functor.Identity.Identity ()
Actual type: Maybe a0 -> QueueState (Maybe a0) ()
現在我想我明白為什么會這樣,但我無法弄清楚如何讓它做我想做的事。 也就是說,使用>>=
來自pop
的鏈接應該能夠進入push
。 我想我可能需要使用StateT轉換器,但我還沒有真正理解它們,所以我正在尋找有關如何實現該功能的幫助。 或者我是否需要以完全不同的方式執行此操作? 謝謝。
這是因為編譯器無法構造無限類型;-)。
更有幫助的是,考慮一下:
runState (pushQueue 2 >> popQueue >>= pushQueue) emptyQueue
popQueue
的類型是popQueue
? QueueState Int (Maybe Int)
。 (想想m (Maybe Int)
)
什么是>>= pushQueue
的類型? QueueState Int Int -> QueueState Int ()
(想想m Int -> m ()
)
所以typechecker試圖統一類型Maybe a
和a
-這些類型的統一的唯一途徑是,如果a
如果無限類型的Maybe (Maybe (Maybe (Maybe ...
。
解決方案是做一些事來處理Nothing
案例。 例如, return ()
或push取決於Maybe。
runState (pushQueue 2 >> popQueue >>= maybe (return ()) pushQueue) emptyQueue
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.