模拟用Haskell单子
表示由输入更新的状态的最佳方式是什么 我模拟物理系统。它有状态(坐标、速度)。状态通过从模拟用Haskell单子,haskell,Haskell,表示由输入更新的状态的最佳方式是什么 我模拟物理系统。它有状态(坐标、速度)。状态通过从stdin获取一些参数(力)的模拟进行更新。每个模拟循环后,结果进入标准输出 程序应在N个周期后停止 我已经用readIORef和writeIORef完成了,但这很难看。一个简单的方法是沿着一个懒惰的(可能是无限的)列表,而不是执行任何显式IO import Control.Monad.State -- Prerequisites: data SimState -- coordinates &am
stdin
获取一些参数(力)的模拟进行更新。每个模拟循环后,结果进入标准输出
程序应在N个周期后停止
我已经用
readIORef
和writeIORef
完成了,但这很难看。一个简单的方法是沿着一个懒惰的(可能是无限的)列表,而不是执行任何显式IO
import Control.Monad.State
-- Prerequisites:
data SimState -- coordinates & velocities.
data SimTVParams -- what's read from input. `instance Read`.
initialState :: SimState
simStep :: SimTVParams -> SimState -> SimState
simStateInfo :: SimState -> String
-- How to do the simulation:
main :: IO ()
main = interact $
unlines . map simStateInfo
. simulate initialState
. map read . lines
simulate :: SimState -> [SimTVParams] -> [SimState]
simulate iState = (`evalState` iState) . mapM (state . step)
where step params oldState = (newState, newState)
where newState = simStep params oldState
您可以使用
管道
在非常高的层次上编写此代码。首先,我假设您已经定义了以下类型、值和函数:
data Status = Status deriving (Show)
data Param = Param deriving (Read)
initialState :: Status
initialState = undefined
update :: Status -> Param -> Status
update = undefined
numCycles :: Int
numCycles = undefined
下面是管道代码:
import Pipes
import qualified Pipes.Prelude as P
main = runEffect $
P.readLn >-> P.take numCycles >-> P.scan update initialState id >-> P.print
您可以将其作为数据处理管道从左到右阅读:
从标准输入读取输入参数。如果到达输入的末尾,它将停止P.readLn
仅允许最多P.take numCycles
参数通过numCycles
使用提供的初始状态和更新功能运行模拟,然后将每个中间状态进一步流到下游P.scan
打印每个中间状态P.print
要了解有关管道库的更多信息,请阅读。谢谢。N步后不会退出。但是我可以通过stdin通过sh中的head-n来完成这个。对于此类任务,停止执行
eof
而不是固定数量的步骤要自然得多。