2010-12-16 51 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