标签: state-monad

Haskell Monad变换器堆栈和类型签名

我正在尝试创建一堆monad变换器,并且无法为我的函数获取正确的类型签名.(我对Haskell还很新)

该堆栈结合了多个StateT变换器,因为我有多个状态需要跟踪(其中两个可能是tupled,但我会在一秒内完成)和一个WriterT用于记录.

这是我到目前为止所拥有的:

module Pass1 where
import Control.Monad.Identity
import Control.Monad.State
import Control.Monad.Writer
import Data.Maybe
import qualified Data.Map as Map
import Types

data Msg = Error String
         | Warning String

type Pass1 a = WriterT [Msg] (StateT Int (StateT [Line] (StateT [Address] Identity))) a


runPass1 addrs instrs msgs = runIdentity (runStateT (runStateT (runStateT (runWriterT msgs) 1) instrs) addrs)


--popLine :: (MonadState s m) => m (Maybe s)
--popLine :: (Monad m) => StateT [Line] m (Maybe Line)
popLine :: (MonadState s …
Run Code Online (Sandbox Code Playgroud)

haskell types state-monad monad-transformers

14
推荐指数
2
解决办法
3046
查看次数

Haskell:map runST

我有一个类型的绑定[ST s (Int, [Int])],我试图runST使用map 应用于每个元素,如下所示:

name :: [ST s (Int, [Int])] --Of Course there is a real value here
map runST name
Run Code Online (Sandbox Code Playgroud)

这给了我一个错误信息

Couldn't match expected type `forall s. ST s b0'
    with actual type `ST s0 (Int, [Int])'
Expected type: [forall s. ST s b0]
  Actual type: [ST s0 (Int, [Int])]
In the second argument of `map', namely `name'
In the expression: map runST name
Run Code Online (Sandbox Code Playgroud)

必须有一些我误解的东西.我知道runST和函数组成,但我不确定这是否适用.

谢谢大家的时间!

haskell state-monad

14
推荐指数
3
解决办法
1016
查看次数

我怎样才能在状态monad中正确添加"撤消"功能?

假设我有一个状态monad,我想对状态进行一些操作,并且可能希望在将来撤消更改.我一般可以这样做得体面吗?

举一个具体的例子,让我们假设状态只是一个Int,操作就是将数字增加一个.

type TestM a = StateT a IO ()

inc :: TestM Int
inc = modify (+ 1)
Run Code Online (Sandbox Code Playgroud)

但是,如果我想跟踪状态的所有历史记录,以防我想要撤消到某个先前的状态,我能想到的最好的方法是将状态包装在堆栈中:对状态的每次修改都会被推送到堆栈,以便我可以通过删除堆栈上的顶部元素来撤消更改.

-- just for showing what's going on
traceState :: (MonadIO m, MonadState s m, Show s) => m a -> m a
traceState m = get >>= liftIO . print >> m

recordDo :: TestM a -> TestM [a]
recordDo m = do
    x <- gets head
    y <- liftIO $ execStateT m x
    modify (y:)

inc' :: …
Run Code Online (Sandbox Code Playgroud)

haskell state-monad

14
推荐指数
1
解决办法
568
查看次数

模拟Haskell中的交互状态对象

我正在编写一个Haskell程序,它涉及模拟一个抽象机器,它具有内部状态,接受输入并提供输出.我知道如何使用状态monad实现这一点,从而产生更清晰,更易于管理的代码.

我的问题是,当我有两个(或更多)有状态对象相互交互时,我不知道如何使用相同的技巧.下面我给出了一个高度简化的问题版本,并勾勒出我到目前为止的内容.

为了这个问题,让我们假设一个机器的内部状态只包含一个整数寄存器,因此它的数据类型是

data Machine = Register Int
        deriving (Show)
Run Code Online (Sandbox Code Playgroud)

(实际的机器可能有多个寄存器,程序指针,调用堆栈等等,但现在不要担心.)在上一个问题之后我知道如何使用状态monad实现机器,所以我不必显式传递其内部状态.在这个简化的示例中,导入后实现如下所示Control.Monad.State.Lazy:

addToState :: Int -> State Machine ()
addToState i = do
        (Register x) <- get
        put $ Register (x + i)

getValue :: State Machine Int
getValue = do
        (Register i) <- get
        return i
Run Code Online (Sandbox Code Playgroud)

这让我可以写出类似的东西

program :: State Machine Int
program = do
        addToState 6
        addToState (-4)
        getValue

runProgram = evalState program (Register 0)
Run Code Online (Sandbox Code Playgroud)

这会将6添加到寄存器,然后减去4,然后返回结果.状态monad跟踪机器的内部状态,以便"程序"代码不必明确跟踪它.

在命令式语言的面向对象样式中,这个"程序"代码可能看起来像

def runProgram(machine):
    machine.addToState(6)
    machine.addToState(-4)
    return machine.getValue()
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如果我想模拟两台彼此交互的机器,我可能会写

def …
Run Code Online (Sandbox Code Playgroud)

monads haskell state-monad lenses haskell-lens

14
推荐指数
2
解决办法
437
查看次数

更严格的严格状态Monad

严格的状态monad定义使用:

m >>= k = State $ \s ->
  case runState m s of
    (a, s') -> runState (k a) s'
Run Code Online (Sandbox Code Playgroud)

但这仍然会泄漏记忆,因为a并且没有s'得到评估.例如,我们可能有一个函数f将大对象作为输入并快速返回(a, s'),但只要a没有评估,输入f就不能被GC.

一个可能的解决方案是f返回seq a (a, s'),但如果我们使用类似的东西MonadRandom,这并不总是可能的,并且状态被封装起来f.是否有这样定义的版本:

m >>= k = State $ \s ->
  case runState m s of
    (!a, !s') -> runState (k a) s'
Run Code Online (Sandbox Code Playgroud)

这已存在于任何地方的图书馆吗?

haskell lazy-evaluation state-monad

13
推荐指数
1
解决办法
564
查看次数

在Haskell中如何"获得"实际/获得/初始状态?

我有一个功能:

test :: String -> State String String
test x = 
    get >>= \test ->
    let test' = x ++ test in
    put test' >>
    get >>= \test2 -> put (test2 ++ x) >>
    return "test"
Run Code Online (Sandbox Code Playgroud)

我几乎可以理解整个函数中发生了什么,并且我开始得到monad的支持.我不明白的是,当我这样做时:

runState (test "testy") "testtest"
Run Code Online (Sandbox Code Playgroud)

'test'中的'get'函数以某种方式获得初始状态"testtest".有人可以打破这个并向我解释一下吗?

我感谢任何回应!

monads haskell state-monad

12
推荐指数
2
解决办法
837
查看次数

在Haskell中快速更新大状态

对于我在Haskell中的矢量图形库,我必须携带一个相当大的状态:线条描边参数,颜色,剪辑路径等.我知道两种方法.引用Haskell-cafe的评论:"我建议你使用具有可变状态的读取器monad,或者使用具有不可变状态的状态monad".

这是我的问题:更新一个大的不可变状态是一个性能杀戮.使用大量的STRef就像在Haskell中编写C一样:它冗长而丑陋.

这是不可变状态:

data GfxState = GfxState {
  lineWidth :: Double,
  lineCap :: Int,
  color :: Color,
  clip :: Path,
  ...
}

setLineWidth :: Double -> State GfxState ()
setLineWidth x = modify (\state -> state { lineWidth = x })
Run Code Online (Sandbox Code Playgroud)

据我所知,"state {lineWidth = x}"创建一个新的GfxState并让旧的GfxState被垃圾收集.当状态很大并经常更新时,这会导致性能下降.

这是可变状态:

data GfxState s = GfxState {
  lineWidth :: STRef s Double,
  lineCap   :: STRef s Int,
  color     :: STRef s Color,
  clip      :: STRef s Path,
  ...
  many more STRefs
}

setLineWidth …
Run Code Online (Sandbox Code Playgroud)

haskell state-monad data-structures

12
推荐指数
3
解决办法
2384
查看次数

基本的Scalaz State问题

我如何State用来模仿行为List.zipWithIndex?到目前为止我提出的(不起作用)是:

def numberSA[A](list : List[A]) : State[Int, List[(A, Int)]] = list match {
  case x :: xs => (init[Int] <* modify((_:Int) + 1)) map { s : Int => (x -> s) :: (numberSA(xs) ! s) }
  case Nil     => state( (i : Int) => i -> nil[(A, Int)] )
}
Run Code Online (Sandbox Code Playgroud)

这基于状态示例非常松散.正如我所说,它不起作用:

scala> res4
res5: List[java.lang.String] = List(one, two, three)

scala> numberSA(res4) ! 1
res6: List[(String, Int)] = List((one,1), (two,1), (three,1))
Run Code Online (Sandbox Code Playgroud)

我可以通过更改case语句的一行来使它工作:

case x …
Run Code Online (Sandbox Code Playgroud)

functional-programming scala state-monad scalaz

12
推荐指数
1
解决办法
1462
查看次数

州monad的目的是什么?

我是一名JavaScript开发人员,可以提升我在函数式编程方面的技能.在管理国家时,我最近碰到了一堵墙.在搜索解决方案时,我在各种文章和视频中对状态monad进行了标记,但我很难理解它.我想知道是不是因为我希望它不是.

我试图解决的问题

在Web客户端中,我从后端获取资源.为了避免不必要的流量,我在客户端创建一个包含已经获取的数据的简单缓存.缓存是我的状态.我希望我的几个模块能够保存对缓存的引用并查询它的当前状态,这个状态可能已被另一个模块修改过.

这当然不是javascript中的问题,因为它可以改变状态,但我想学习更多关于函数式编程的知识,我希望状态monad会帮助我.

我期待什么

我以为我可以这样做:

var state = State.of(1);
map(add(1), state);
state.evalState() // => 2 
Run Code Online (Sandbox Code Playgroud)

这显然不起作用.国家总是1.

我的问题

我对状态monad的假设是错误的,还是我只是错误地使用它?

我意识到我可以这样做:

var state = State.of(1);
var newState = map(add(1), state);
Run Code Online (Sandbox Code Playgroud)

...并且newState将是2的状态.但是在这里我并没有真正看到状态monad的使用,因为我将不得不创建一个新实例以便更改值.这对我来说似乎总是在函数式编程中完成,其中值是不可变的.

monads functional-programming state-monad

12
推荐指数
2
解决办法
2550
查看次数

来自GHC.IO的`ioToST`和`unsafeIOToST`有什么区别?

GHC.IO中,差异和预期用途有何用途ioToSTunsafeSTToIO定义?

-- ---------------------------------------------------------------------------

-- Coercions between IO and ST

-- | A monad transformer embedding strict state transformers in the 'IO'
-- monad.  The 'RealWorld' parameter indicates that the internal state
-- used by the 'ST' computation is a special one supplied by the 'IO'
-- monad, and thus distinct from those used by invocations of 'runST'.
stToIO        :: ST RealWorld a -> IO a
stToIO (ST m) = IO m

ioToST        :: IO …
Run Code Online (Sandbox Code Playgroud)

io haskell ghc state-monad

11
推荐指数
2
解决办法
438
查看次数