我正在尝试将Spider Solitaire播放器编写为Haskell学习练习.
我的main函数将为playGame每个游戏(使用mapM)调用一次函数,传入游戏编号和随机生成器(StdGen).该playGame函数应该返回一个Control.Monad.Statemonad和一个IO monad,其中包含一个String显示游戏画面并Bool指示游戏是赢还是输的.
如何将Statemonad与IOmonad 结合起来获得返回值?`playGame的类型声明应该是什么?
playGame :: Int -> StdGen a -> State IO (String, Bool)
Run Code Online (Sandbox Code Playgroud)
是对的State IO (String, Bool)吗?如果不是,它应该是什么?
在main,我计划使用
do
-- get the number of games from the command line (already written)
results <- mapM (\game -> playGame game getStdGen) [1..numberOfGames]
Run Code Online (Sandbox Code Playgroud)
这是正确的打电话playGame吗?
假设我有一个monadT:
type Wrap a = ReaderT Env ( StateT Int ( StateT Int Identity ) ) a
Run Code Online (Sandbox Code Playgroud)
这里要注意的重要一点是,一个StateT正在包装另一个,并且两者都包含在第三个MonadT内,即ReaderT.
以及相应的runWrap函数以方便:
type Env = Map.Map Char Integer
runWrap :: Env -> Int -> Int -> Wrap a -> a
runWrap env st1 st2 m = runIdentity $ evalStateT ( evalStateT ( runReaderT m env ) st2 ) st1
Run Code Online (Sandbox Code Playgroud)
一个通用的tock状态monad:
tock :: (Num s, MonadState s m) => m ()
tock = do modify (+1)
Run Code Online (Sandbox Code Playgroud)
我现在创建一个包裹monadT,其中我使用tock:
aWrap :: Wrap ( Int, Int ) …Run Code Online (Sandbox Code Playgroud) 我只是在学习Haskell,并试图找出实现视线算法的最惯用的方法.
我发现的演示代码使用状态monad,但对我来说(我只是初学者)递归传递状态似乎更简单.我在这里错过了什么?有性能问题吗?
查找代码:http://www.finalcog.com/bresenham-algorithm-idiomatic-haskell
谢谢,
克里斯.
试图学习用Gtk2Hs编写应用程序我遇到了困难,弥合了事件驱动的Gtk2HS与模型的持久状态之间的差距.所以为了简化,让我说我有这个简单的应用程序
module Main where
import Graphics.UI.Gtk
import Control.Monad.State
main = do
initGUI
window <- windowNew
button <- buttonNew
set button [buttonLabel := "Press me"]
containerAdd window button
-- Events
onDestroy window mainQuit
onClicked button (putStrLn ---PUT MEANINGFUL CODE HERE---)
widgetShowAll window
mainGUI
Run Code Online (Sandbox Code Playgroud)
我的应用程序的状态是按下按钮的次数.看到像这样的其他帖子,他们依赖于MVars或IORefs,这对我来说似乎并不令人满意,因为将来也许我会想要重构代码,以便状态存在于自己的上下文中.
我认为解决方案应该使用状态monad使用步骤函数,如:
State $ \s -> ((),s+1)
Run Code Online (Sandbox Code Playgroud)
但我不确定其含义,如何在上面的代码中执行此操作,或者即使该monad是我的问题的正确解决方案.
Control.Monad.ST在base包中包含runST运行严格的状态变换器monad:
runST :: (forall s. ST s a) -> a
Run Code Online (Sandbox Code Playgroud)
但是,我需要一个通用版本runST:
runSTCont :: (forall s . (forall b . ST s b -> b) -> a) -> a
runSTCont f = f $ \m -> runST $ unsafeCoerce m
Run Code Online (Sandbox Code Playgroud)
我的问题是:这是否unsafeCoerse安全使用?(我想是的,因为据我所知,索引的唯一目的s是防止s在结果中泄漏索引值a.runSTCont不能泄漏s索引值的类型,所以应该没问题.)
请注意,runST在来表示runSTCont这样runSTCont至少一般为runST:
runST' :: (forall s. ST s a) -> a
runST' m = …Run Code Online (Sandbox Code Playgroud) 你如何在OCaml中实现反向状态monad?(因为它很大程度上依赖于懒惰,我想必须使用标准库中的Lazy模块).
我试图采取例如ExceptT a (StateT A M),对于一些具体类型A和monad M,并将它们包装到我的新自定义monad中.
首先,我确定了StateT A M在其他环境中经常出现,因此我决定这将是最好的单独包装在一个单子M1,然后包装ExceptT a M1成M2.
所需的属性是make M1和的M2实例MonadState和类M(假设它被调用MyMonadClass).也M2应该是一个实例MonadError.
首先我从简单类型的同义词开始:
type MyState = StateT A M
type MyBranch a = ExceptT a MyState
Run Code Online (Sandbox Code Playgroud)
然后我想我会首先勾画实例声明(没有实现实例),这就是我第一次被卡住的地方.instance MonadState A (MyState)似乎不是正确的语法.我以为我必须创建newtype MyState' a = StateT a M然后type MyState = MyState A(不要在没有必要的地方使用语言扩展).
然而,一旦我开始将同义词转换为newtype声明,我开始失去与StateT A M和 …
反向状态monad是非常好的,令人兴奋的Haskell语言表达性和懒惰评价的例子.但要理解这个单子并不容易.此外,很难找到一些令人信服的现实生活中的例子,说明你可以使用Reverse State monad比使用该语言中的任何其他工具更容易.
反向状态 monad的定义方式如下:
newtype RState s a = RState { runRState :: s -> (a,s) }
instance Monad (RState s) where
return x = RState $ (,) x
RState sf >>= f = RState $ \s ->
let (a, past) = sf future
(b, future) = runRState (f a) s
in (b, past)
Run Code Online (Sandbox Code Playgroud)
它已经有一些例子和用法,但我发现它们并不实用.
RState.Writer模仿,RState但来吧.不是真正的生活例子:)我也知道tardis包但没有这个库的教程,文档示例真的是抽象的,没有那么多人真正理解它.最接近我想要的是本教程,但它有一个例子tardis,而不仅仅是 …
我正在尝试定义一系列具有不同类型状态的状态机。特别是,更“复杂”的状态机具有通过组合更简单状态机的状态而形成的状态。
(这类似于面向对象的设置,其中一个对象具有多个也是对象的属性。)
这是我想要实现的简化示例。
data InnerState = MkInnerState { _innerVal :: Int }
data OuterState = MkOuterState { _outerTrigger :: Bool, _inner :: InnerState }
innerStateFoo :: Monad m => StateT InnerState m Int
innerStateFoo = do
i <- _innerVal <$> get
put $ MkInnerState (i + 1)
return i
outerStateFoo :: Monad m => StateT OuterState m Int
outerStateFoo = do
b <- _outerTrigger <$> get
if b
then
undefined
-- Here I want to "invoke" innerStateFoo
-- which should …Run Code Online (Sandbox Code Playgroud) 我一直在尝试围绕monad的概念,我一直在尝试以下示例:
我有一个Editor数据类型,表示文本文档的状态和一些工作的功能.
data Editor = Editor {
lines :: [Line], -- editor contents are kept line by line
lineCount :: Int, -- holds length lines at all times
caret :: Caret -- the current caret position
-- ... some more definitions
} deriving (Show)
-- get the line at the given position (first line is at 0)
lineAt :: Editor -> Int -> Line
lineAt ed n = ls !! n
where
ls = lines ed
-- get …Run Code Online (Sandbox Code Playgroud)