2010-12-16 26 views
2

的順序成員我有如此生成實體的無窮列表:生成一個無限列表

entities = 
    let f x = x ++ "'" 
    in "x" : "y" : "z" : map f entities 

我想以限定每個invokation返回一個新的實體的功能。像這樣:

> nextEntity 
x 
> nextEntity 
y 
. 
. 
. 

我想這是國家monad的地方,但會對指針感激不盡。

一些背景:如果您嘗試在FOL中表示自然語言句子,則需要爲您的實體命名變量。 「約翰愛瑪麗」需要兩個變量(一個是約翰和一個是瑪麗),「約翰給瑪麗一本書」需要三個變量(約翰,瑪麗,這本書)等等。我需要的是一種生成新的在處理句子時遇到的每個「事物」的變量名稱。

所以我想使用的函數必須跟蹤哪些已經生成,並在invoke返回下一個。

回答

4

對於一個函數來說,它必須具有某種狀態,當它被調用時它會發生變化,這是純粹的Haskell函數無法做到的。你可以使用State monad,但我認爲無論它可能會有更好的方法來解決你的問題。

這裏有一個如何可能做到這一點的國家單子裏面

nextEntity :: State Int String 
nextEntity = do 
       s <- get 
       put (s+1) 
       return (entities !! s) 

這比你可以在計算中使用它的國家單子像這裏面:

someCalculation = do 
        s1 <- nextEntity 
        s2 <- nextEntity 
        (do something with them) 

如此不同的價值觀會得到綁定到s1和s2。但是,所有這些只應該被視爲對州政府單位的練習,因爲我確信有更好的解決方案來處理你正在做的事情。

+1

除非他試圖對Haskell感到好奇。雖然答案很好。 – luqui 2010-12-16 11:04:08

5

我想定義一個函數,它在每個invoke上返回一個新的實體。像這樣:

由於Haskell是一種純粹的函數式編程語言,所以這在定義上是不可能的。任何Haskell函數都會爲相同的參數返回相同的值。因此沒有參數的函數是恆定的。

我想這對國家來說是單子的地方,

是的,的確是。狀態monad表示一個可以改變的隱藏狀態的計算。使用do構造,您可以將有狀態的計算組合成更大的共享狀態。特別是,每個計算只是將新狀態傳遞給連續的狀態。

雖然用法很簡單。

nextEntity :: State [a] a 
nextEntity = do 
    entity:rest <- get 
    put rest 
    return entity 

test = do 
    e1 <- nextEntity 
    e2 <- nextEntity 
    e3 <- nextEntity 
    return [e1, e2, e3] 

res = fst $ runState test entities 
1

是的,國家Monad是你想要的。Nextentities可以這樣寫:

nextEntity :: State [a] a 
nextEntity = modify tail >> gets head 

我們可以寫一個函數,讓你的第一個100元這樣的:

test = sequence (replicate 100 nextEntity) 

這樣它們打印:

main = sequence_ . map print . evalState test $ entities 
+1

更短,並按正確的順序:'獲取頭<*修改尾巴'。或者'做一個< - 得到頭;修改尾巴;沒有'Control.Applicative'返回一個''。 – ephemient 2010-12-16 19:35:07