2016-06-02 1 views
0

이전 코드 리뷰로 재생 simple-db. 코드를 줄이기 위해 상태 모나드를 추가 할 때 막히게됩니다.haskell kv 데이터베이스에 상태 모나드 추가

나는 어떻게 든 제대로하지 않는다고 느낍니다. repl cmd = getCmd >>= execCmd cmd >>= displayResult >>= continueexecCmd의 인터페이스를 변경하면 해당 라인을 따라 모든 기능이 변경됩니다.

이 접근법을 따르면 어떻게 작동합니까?

state 모나드를 사용하여 제안 된 리펙토링을 수행하는 올바른 방법은 무엇입니까? 우선 들어

--import qualified 
import Data.Map as M 
import Control.Monad.State 

type History = [String] 

data Result = Result (Maybe String) Bool 

data Command = Invalid | End | Get String | Set String String 
data DB = DB (M.Map String String) 


execCmd :: Command -> State DB Result 
execCmd (Set key val) = do 
    ([email protected](DB map), r) <- get 
    let newMap = M.insert key val map 
    put ((DB newMap), r) 
    return $ Result Nothing False 
execCmd (Get key) = do 
    ([email protected](DB map), r) <- get 
    return $ Result (M.lookup key map) False 
execCmd End = do 
    return $ Result Nothing True 
execCmd Invalid = do 
    return $ Result Nothing False 

getCmd = getLine >>= return . parseCmd 

parseCmd :: String -> Command 
parseCmd s = 
    case words s of 
    ("set":key:value:_) -> Set key value 
    ("get":key:_)  -> Get key 
    ("end":_)   -> End 
    _     -> Invalid 

displayResult :: Result -> IO Result 
displayResult [email protected](Result (Just s) _) = putStrLn s >> return r 
displayResult r      = return r 

continue :: Result -> IO() 
continue (Result _ end) = if end then return() else repl 

repl cmd = getCmd >>= execCmd cmd >>= displayResult >>= continue 

startState = ((DB M.empty), (Result Nothing False)) 

--main = repl Invalid 

답변

1

, 코드를 확인 입력 그래서 그냥 execCmd의 첫 부분에 집중하지 않습니다

execCmd :: Command -> State DB Result 
execCmd (Set key val) = do 
    ([email protected](DB map), r) <- get 
    let newMap = M.insert key val map 
    put ((DB newMap), r) 
    return $ Result Nothing False 

은 분명히이 getput이기 때문에 작동하지 않을 쌍을 (DB, r)과 함께 사용하고 있지만 서명 유형에 따르면 상태 유형은 DB뿐입니다.

여기에 r은 무엇입니까? 너는 그것을 필요로 하느냐? execCmd의이 정의는 유형 서명과 일치합니다.

execCmd :: Command -> State DB Result 
execCmd (Set key val) = do 
    [email protected](DB map) <- get 
    let newMap = M.insert key val map 
    put (DB newMap) 
    return $ Result Nothing False