我正在做一个代码翻译项目,需要我生成变量名.我生成的名称都不应该是彼此重复的.
我真的很沮丧,因为这将是一个愚蠢的简单和优雅的Python生成器功能.
我之前做的方式是通过递归调用我的翻译代码传递一个计数器变量,并将(可能递增的)计数器传递回基本上每个函数的返回值.
这真的很乱:它增加了一个额外的参数来跟踪这些功能; 更糟糕的是它仍然迫使我使用凌乱的元组返回值,否则我将有一个简单的一元返回值.
在Haskell的短暂时间里,我从来没有真正熟练使用monad,但我有一个想法,我可以使用Statemonad 上的包装来模拟全局计数器变量.在试图修改monad并制作我自己的monad三天之后,然后试图改变别人的monad来生成我需要的值,我终于使用其他人的高级monad来自我辞职了(也许有一些改动.)
我已经将MonadSupply和MonadUnique模块确定为一对可能提供我需要的简单接口的一对.不幸的是我无法弄清楚如何使用它们.
特别是MonadSupply模块文档提供了这个很好的示例用例:
runSupplyVars x = runSupply x vars
where vars = [replicate k ['a'..'z'] | k <- [1..]] >>= sequence
Run Code Online (Sandbox Code Playgroud)
看起来像我想要的!一旦我得到了编译模块,我在解释器中检查了这个函数的类型:
> :t runSupplyVars
runSupplyVars :: Supply [Char] a -> Identity (a, [[Char]])
Run Code Online (Sandbox Code Playgroud)
我已经尝试将很多(数小时)不同的东西传递给这个功能,但没有成功.我也尝试将函数传递给其他各种函数,以查看它们是否会隐式提供我需要的参数.到目前为止没有运气.
有人可以提供此runSupplyVars功能的示例用例吗?
是否有可能做我正在考虑的事情?我希望有一个我可以在程序中的任何地方调用的函数,它将在每次调用时为我提供不同的变量名或整数.
我试图找到将以下有状态命令式代码段转换为纯函数表示的最优雅方式(最好在 Haskell 中使用其 Monad 实现提供的抽象)。但是,我还不擅长使用转换器等组合不同的 monad。在我看来,在学习如何自己做时,分析他人对此类任务的看法最有帮助。命令式代码:
while (true) {
while (x = get()) { // Think of this as returning Maybe something
put1(x) // may exit and present some failure representation
}
put2() // may exit and present some success representation
}
Run Code Online (Sandbox Code Playgroud)
当get返回时Nothing我们需要继续执行put2,当get返回时Just x我们希望x被传递给put1并且仅在put1失败或循环时才短路。基本上put1并且put2可能会终止整个事情或移动到以下语句以某种方式改变底层状态。get可以成功并调用put1和循环或失败并继续put2。
我的想法是:
forever $ do
forever (get >>= put1)
put2
Run Code Online (Sandbox Code Playgroud)
为什么我要寻找这样的东西是因为 …
haskell functional-programming imperative-programming state-monad monad-transformers
我正在尝试使用scalaz实现Depth-First Search的不同实现.
这种遍历应该与深树状结构一起处理.
主要思想 - 从属元素应该根据一些"状态"生成.例如,标记为已显示元素的集合,以避免将来出现.
这是我最简单的实现
import scalaz._
import scalaz.syntax.monad._
import scalaz.State._
abstract class DepthFirstState[E, S] {
def build(elem: E): State[S, List[E]]
def go(start: E): State[S, List[E]] = for {
xs ? build(start)
ys ? xs.traverseSTrampoline(go)
} yield start :: ys.flatten
}
Run Code Online (Sandbox Code Playgroud)
我们可以创建最简单的算法来测试它如何处理深度搜索
class RangeSearchState extends DepthFirstState[Int, Int] {
def build(elem: Int) = get[Int] map (limit ? if (elem < limit) List(elem + 1) else Nil)
}
Run Code Online (Sandbox Code Playgroud)
它只是一个降级为链表的树,其中每个元素i都有单个子元素,i+1直到它达到limit …
我试图解决"AI - 现代方法"一书中的问题2.8,该书涉及一组单元格并选择随机移动来导航网格.
2.7为X m矩形房间实施环境,每个方格有5%的可能含有污垢,n和m从8到15的范围内随机选择.
2.8为练习2.7的环境设计并实施纯反射剂,忽略回家的要求,并测量其性能.
所以我使用了两个状态monad - 一个Grid用作状态,另一个StdGen用作状态.代码编译时没有任何错误,但是当我从GHCi运行它时,它会卡住并且不会返回.
代码的相关部分:
支持代码
type RandomState = State StdGen
makeGrid :: (Int, Int) -> (Int, Int) -> Float -> RandomState Grid
doAction :: Action -> Cleaner -> State Grid Cleaner
getRandomR :: Random a => (a, a) -> RandomState a
getRandomR limits = do
gen <- get
let (val, gen') = randomR limits gen
put gen'
return val
chooseAction :: Percepts -> RandomState Action
chooseAction percepts
| PhotoSensor `elem` …Run Code Online (Sandbox Code Playgroud) 我仍然是Haskell的新手,我想我现在已经超过了我的头脑.我的代码如下所示.
data World = World {
intStack :: [Int],
boolStack :: [Bool]
} deriving Show
instance IntStack World where
getIntStack = intStack
putIntStack ints (World _ bools) = World ints bools
instance BoolStack World where
getBoolStack = boolStack
putBoolStack bools (World ints _) = World ints bools
class IntStack a where
getIntStack :: a -> [Int]
putIntStack :: [Int] -> a -> a
class BoolStack a where
getBoolStack :: a -> [Bool]
putBoolStack :: [Bool] -> a -> a
(<=>) …Run Code Online (Sandbox Code Playgroud) 我正在构建代码以获得理解,实际上是Solitaire求解器.我有一个简单的暴力实现,它使用状态monad,实际上只是为了证明我可以使用它(它只保留每个移动的计数).但是现在我想使用Unboxed Mutable数组来记录被访问的板,从而在我到达已经通过另一条路径访问的板位置时快速评估路径.似乎ST monad不允许我线程隐式状态,但是我必须使用ST(或IO)才能访问Mutable数组.因此,似乎我必须结合两个Monads - State来线程化状态(实际上包括一个Mutable数组),另一个(ST)来获得Mutable数组函数.
我正在编写一些代码,使用StateTmonad转换器来跟踪一些有状态信息(日志记录等).
我传给的monad StateT非常简单:
data CheckerError a = Bad {errorMessage :: Log} | Good a
deriving (Eq, Show)
instance Monad CheckerError where
return x = Good x
fail msg = Bad msg
(Bad msg) >>= f = Bad msg
(Good x) >>= f = f x
type CheckerMonad a = StateT CheckerState CheckerError a
Run Code Online (Sandbox Code Playgroud)
这只是一个Left和Right变型.
困扰我的是它的定义fail.在我的计算中,我在这个monad中产生了很多信息,我想在失败的时候保留这些信息.目前我唯一能做的就是将所有内容转换为a String并Bad使用String传递的as参数创建一个实例fail.
我想做的是:
fail msg = do
info <- getInfoOutOfTheComputation …Run Code Online (Sandbox Code Playgroud) 如果一个函数及其参数(也是一个函数)都改变了状态,我对状态monad的用法有疑问.
这里是简短信息:
函数foo更改状态
函数bar更改状态
我想打电话:
foo bar
Run Code Online (Sandbox Code Playgroud)
如果我bar单独打电话,状态设置为"bar"
如果我打电话foo bar然后状态只是"foo"而不是"foobar",所以似乎bar没有改变状态,我不明白为什么.
任何澄清表示赞赏.
这是完整的代码:
module Main where
import Control.Monad.State
main :: IO ()
main = do
a <- execStateT test1 ""
print a
a <- execStateT test2 ""
print a
type MyState = String
type MyStateMonadT = StateT MyState IO
test1 :: MyStateMonadT ()
test1 = do
bar
return ()
test2 :: MyStateMonadT ()
test2 = do
foo bar
return ()
data …Run Code Online (Sandbox Code Playgroud) import Control.Monad.State.Lazy
type Queue a = [a]
push :: a -> State (Queue a) ()
push x = state (\xs -> ((),xs++[x]))
pop :: State (Queue a) a
pop = state (\(x:xs) -> (x,xs))
queueManip :: State (Queue Int) Int
queueManip =
do
mapM_ push [1..]
a <- pop
return a
main :: IO()
main = do
let (a,_) = runState queueManip []
print a
Run Code Online (Sandbox Code Playgroud)
不mapM_应该懒惰吗?除了实现队列不应该复杂O(1)吗?
因为追加(++)本身就是懒惰......
我正在试验Haskell Control.Monad.State,试图迭代一个字符串或整数列表,计算它们,并用整数替换字符串条目0.我已设法完成计数部分,但未能创建替换列表.这是我的代码正确打印[3,6]到屏幕上.如何让它创建所需的列表[6,0,3,8,0,2,9,1,0]?
module Main( main ) where
import Control.Monad.State
l = [
Right 6,
Left "AAA",
Right 3,
Right 8,
Left "CCC",
Right 2,
Right 9,
Right 1,
Left "D"]
scanList :: [ Either String Int ] -> State (Int,Int) [ Int ]
scanList [ ] = do
(ns,ni) <- get
return (ns:[ni])
scanList (x:xs) = do
(ns,ni) <- get
case x of
Left _ -> put (ns+1,ni)
Right _ -> put (ns,ni+1) …Run Code Online (Sandbox Code Playgroud)