我们正在开发一个内部使用状态monad的模型文件系统.我们有一个类型类,其操作如下:
class Monad m => FS m where
isDirectory :: Path -> m Bool
children :: Path -> m [Path]
...
Run Code Online (Sandbox Code Playgroud)
我们正在努力一点点交互式解释,将提供类似的命令cd,ls,cat,等等.解释器中的操作可以这样写:
fsop :: FS m => Operation -> m Response
Run Code Online (Sandbox Code Playgroud)
定义Operation和Response不重要; 如果你愿意,把它们当作弦乐.
我试图解决的问题是在I/O monad中编写一个顶层循环来解释文件系统Operation并打印响应.如果IO是FS的一个实例(也就是说,如果我们直接使用IO monad),生活会很简单:我们可以写
loop :: Path -> IO ()
loop currentDir = do
op <- getLine
case read op of
ChangeDir d -> loop d -- should test 'isDirectory d', but let's not
Ls …Run Code Online (Sandbox Code Playgroud) 我正在玩State monad,我不知道在这段简单的代码中是什么导致了堆栈溢出.
import Control.Monad.State.Lazy
tick :: State Int Int
tick = do n <- get
put $! (n+1)
return n
million :: Int
million = snd $ runState (mapM_ (const tick) [1..1000000]) 0
main = print million
Run Code Online (Sandbox Code Playgroud)
注意 我只想知道在这段代码中导致问题的原因,任务本身本身并不重要.
我正在努力,Data.Fresh并且Control.Monad.Trans.Fresh,正在进行中.定义用于生成新变量的接口,以及实现此接口的monad变换器.
我最初认为可以Applicative为我实现实例,FreshT v m只有Applicative m存在的唯一要求.但是,我卡住了,似乎我需要Monad m.不相信我的Haskell的福,我再转向变压器包,并且很惊讶我发现Control.Monad.Trans.State.Lazy和.Strict:
instance (Functor m, Monad m) => Applicative (StateT s m) where
pure = return
(<*>) = ap
Run Code Online (Sandbox Code Playgroud)
所以这是我的问题:是否可以使用以下实例头创建具有等效语义的实例?
instance (Applicative m) => Applicative (StateT s m) where
Run Code Online (Sandbox Code Playgroud) 让我们说我有一个功能
f :: State [Int] Int
Run Code Online (Sandbox Code Playgroud)
和功能:
g :: StateT [Int] IO Int
Run Code Online (Sandbox Code Playgroud)
我想用f在g,并通过他们之间的状态.是否有库函数
StateT (return . runState f)?或者一般来说,给定一个具有相应monad的monad变换器,它有一个库函数吗?
我正绕着国家单子行道.琐碎的例子很容易理解.我现在转向一个现实世界的案例,其中域对象是复合的.例如,使用以下域对象(它们没有多大意义,只是纯粹的例子):
case class Master(workers: Map[String, Worker])
case class Worker(elapsed: Long, result: Vector[String])
case class Message(workerId: String, work: String, elapsed: Long)
Run Code Online (Sandbox Code Playgroud)
考虑到Worker作为S类型的State[S, +A]单子它很容易写几个组合子这样的:
type WorkerState[+A] = State[Worker, A]
def update(message: Message): WorkerState[Unit] = State.modify { w =>
w.copy(elapsed = w.elapsed + message.elapsed,
result = w.result :+ message.work)
}
def getWork: WorkerState[Vector[String]] = State { w => (w.result, w) }
def getElapsed: WorkerState[Long] = State { w => (w.elapsed, w) }
def updateAndGetElapsed(message: Message): WorkerState[Long] = …Run Code Online (Sandbox Code Playgroud) 以下程序使用由Tardis monad 提供的向后行进状态.
{-# LANGUAGE RecursiveDo #-}
import Control.Monad.Tardis
lastOccurrence :: Int -> Tardis [Int] () Bool
lastOccurrence x = mdo
sendPast (x : xs)
xs <- getFuture
return (not (elem x xs))
lastOccurrences :: [Int] -> Tardis [Int] () [Bool]
lastOccurrences xs = mapM lastOccurrence xs
main :: IO ()
main =
print $ flip evalTardis ([], ()) $ lastOccurrences [3,4,6,7,4,3,5,7]
Run Code Online (Sandbox Code Playgroud)
如何用反向状态 monad 替换Tardis monad?根据我的以下提议,main永远循环而不是[False,False,True,False,True,True,True,True]像上面的程序一样打印
.
{-# LANGUAGE RecursiveDo #-}
import Control.Monad.RevState
lastOccurrence …Run Code Online (Sandbox Code Playgroud) monads haskell functional-programming lazy-evaluation state-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) 我有一个类型的绑定[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中实现一个heapsort.我认为Statemonad将是这样做的正确选择,因为堆积很大程度上依赖于在单个结构内部移动数据(并且do符号将是有用的).此外,我希望能够巩固我对monad的理解.
在这些示例State单子在了解你的Haskell(和数量的其他 教程),说的是State被定义为:
newtype State s a = State { runState :: s -> (a,s) }
Run Code Online (Sandbox Code Playgroud)
我应该将类型的函数s -> (a,s)(可能在其他参数中,也可能不在其他参数中)传递给State值构造函数.所以我的函数看起来像这样:
pop :: Ord a => State (Heap a) a
pop = State pop'
pop' :: Ord a => Heap a -> (a, Heap a)
-- implementation of pop' goes here
push :: Ord a => a -> State (Heap a) () …Run Code Online (Sandbox Code Playgroud) 我正在编写一个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) state-monad ×10
haskell ×9
monads ×6
haskell-lens ×1
interactive ×1
interpreter ×1
lenses ×1
scala ×1
state ×1
types ×1