2013-06-04 34 views
1

我需要圍繞哈斯克爾國家monad包裹我的頭,我有一些問題。 這個任務是實現一個函數countConcat它將字符串與狀態monad連接起來並且函數extractCC它得到了這個函數的結果。與哈斯克爾狀態monad字符串連接

所以extractCC ((return 0) >>= countConcat "a" >>= countConcat "b" >>= countConcat "c")將產生(3,「ABC」)

據我瞭解countConcat將是怎樣的一個機械手功能及extractCC應該包含某種runState的,對不對?

任何tipps或ressources讓我走向正確的方向是高度讚賞。 (從來就已經通過維基和learnyouahaskell部分,但仍然感覺與此相當愚蠢的)

+3

試着寫它不首先使用狀態,即作爲一個函數'字符串 - >(智力,字符串) - >(Int,String)'。然後再次查看狀態說明以查看該函數如何映射到monad。初始狀態也是'(0,「」)'(在第一個'return'中)。 –

+0

感謝您的輸入,我已經嘗試過對沒有狀態的函數進行建模,這很容易。我的問題是更貼合countConcat的簽名和實施倉操作者對國家鏈接 – floAr

回答

5

試試這個第一

concat' :: String -> State (Int,String)() 
concat' s = do 
    (c,st) <- get 
    put (c+1, st ++ s) 

您可以通過

> runState (concat' "A" >> concat' "B" >> concat' "C") (0,"") 
((),(3,"ABC")) 

我覺得這個運行如果你瞭解state monad,你可以根據需要修改上面的例子。

4

感謝薩特維克,我解決了這個問題。這是我最終的解決方案:

newtype State s a = State {runState :: s -> (a,s)} 

instance Monad (State s) where 
    return x = State (\s -> (x,s)) 
    (State h) >>= f = State (\s -> let (a, newState) = h s 
             (State g)  = f a 
            in g newState) 

         -- Save new state 
countConcat :: String -> Int -> State String Int 
countConcat s i =do 
    st <- get -- get current string 
    put ((st ++ s)) -- put conc. string 
    return (i+1) -- return new counter 


extractCC f =(runState f ("")) --run the function, staring with an empty string 


-- Helper from the wiki 
put newState = State $ \_ -> ((), newState) 
get = State $ \st -> (st, st) 

-- extractCC ((return 0) >>= countConcat "a" >>= countConcat "b" >>= countConcat "c") 
-- (3,"abc") 
0

如果從Control.Arrow使用first組合子,那麼:

countConcat :: String -> State (String,Int)() 
countConcat s = modify ((<> s) *** (+1)) 
+0

工作這是非常陌生的我,所以我讀了很多關於Haskell的箭頭類型。我認爲我現在明白了***,但是由於<>的原因,我無法運行它,我是否需要在這裏輸入特殊的內容? – floAr