2017-04-04 21 views
3

私は述語pとリストを取る関数を書いています。 は([value],[state])を返します。最初のリストにはpを渡す要素が含まれ、2番目の要素には含まれていない要素が含まれています。私は状態モナド:値を変更せずに状態を変更する

runState (myFunc even [1,2,3,4,5]) [] 

を実行したときしかし、私は失敗した要素が誤っ[value]に格納されている([2,4,5,3,1],[5,3,1])を取得します。これは状態と値の両方を更新するgetが原因だと信じていますが、状態を更新して値だけを残す方法を見つけることができませんでした。

myFunc :: (a->Bool) -> [a] -> State [a] [a] 
myFunc _ [] = do 
    a <- get 
    return a 
myFunc p (x:xs) = do 
    if (p x) then do 
     s <- myFunc p xs 
     let ret = (x:s) 
     return ret 
    else do 
     s <- get 
     put(x:s) 
     myFunc p xs 
+0

私はあなたの例をコンパイルするためにいくつかのコードの配置の問題を修正 - 彼らはあなたの好みに合わせていない場合は、それらを元に戻す気軽に! – Alec

+0

あなたの基本ケースが問題です。また、関数は '([value]、[state])'を返さず、 'State [a] [a]'を返します。しかし、それを変更したいのであれば、それもベースケースにあるでしょう。 – Alec

答えて

2

あなたのmyFunc _ []の定義は実際に値を状態に入れています。あなたは実際にちょうどそれがパスの空のリストになりたい:

myFunc _ [] = return [] 

とあなたはおそらく、その結果を順に返すようにしたい:それはおそらくだにもかかわらず

myFunc :: (a -> Bool) -> [a] -> State [a] [a] 
myFunc _ [] = return [] 
myFunc p (x:xs) = do 
    passes <- myFunc p xs 

    if p x then 
     return (x:passes) 
    else do 
     modify (x:) 
     return passes 

側クールな方法は、それを書くために状態での運動やpartitionすでに存在している、

import Data.Bifunctor 

partition f = foldr m ([], []) 
    where m x = (if f x then first else second) (x:) 
+5

それは問題ではないことは分かっていますが、 'Control.Arrow'の代わりに' Data.Bifunctor'から 'first'をインポートすることをお勧めします。比較的新しいHaskellユーザーは、「Bifunctor」が「Arrow」のものよりも理解しやすいでしょう。 – dfeuer

+0

@dfeuerよろしくお願いします。 – Ryan

関連する問題