2017-04-04 45 views
3

我在寫一個函數,它需要一個謂詞p和一個列表。它 返回([value],[state])其中第一個列表包含通過p的元素,第二個包含不包含的元素。然而,當我運行State Monad:修改狀態而不修改值

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

我得到([2,4,5,3,1],[5,3,1]),其中失敗的元素被不正確地存儲在[value]。我相信這是由於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

我知道這並不重要,但我建議從'Data.Bifunctor'而不是'Control.Arrow'導入'第一個'。一個相對較新的Haskell用戶更可能理解「Bifunctor」的含義,而不是「Arrow」的含義。 – dfeuer

+0

@dfeuer好的電話。 – Ryan