簡體   English   中英

使用Maybe with State Monad

[英]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 aa -這些類型的統一的唯一途徑是,如果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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM