Haskell addToLeftPlayerPos的正确实现是什么
我试图继续函数式反应式编程,但我被第4.2节中的第二个示例卡住了 我得到了reader transformer启动并运行的第一个示例:Haskell addToLeftPlayerPos的正确实现是什么,haskell,monads,frp,reader,writer,Haskell,Monads,Frp,Reader,Writer,我试图继续函数式反应式编程,但我被第4.2节中的第二个示例卡住了 我得到了reader transformer启动并运行的第一个示例: module Main where import FRP.BearRiver import Control.Monad.Trans.MSF.Reader type Game = Ball type Ball = Int type GameEnv = ReaderT GameSettings data GameSettings = Game
module Main where
import FRP.BearRiver
import Control.Monad.Trans.MSF.Reader
type Game = Ball
type Ball = Int
type GameEnv = ReaderT GameSettings
data GameSettings
= GameSettings
{ leftPlayerPos :: Int
, rightPlayerPos :: Int
}
ballToRight :: Monad m => MSF (GameEnv m) () Ball
ballToRight =
count >>> arrM addToLeftPlayerPos
where
addToLeftPlayerPos =
(\n -> (n +) <$> asks leftPlayerPos)
hitRight :: Monad m => MSF (GameEnv m) Ball Bool
hitRight = arrM (\i -> (i >=) <$> asks rightPlayerPos)
一些措辞
当您有一个转换器堆栈时,您必须“提升”您的操作以运行内部monad函数。例如:
type MyMonad a = Transformer1 (Transformer2 IO) a
这里的堆栈是IO的Transformer2的Transformer1。“外部”单子是Transformer1,它将Transformer2与IO的最内部(或底部)单子封装在一起。在您的例子中,堆栈实际上是某个未知monadm
的读卡器的编写器,一切正常
现在,如果我们想从函数g::MyMonad
中运行f::Transformer2 IO a
,我们必须lift f
。类似地,如果我们有getLine::IO String
并且希望从g::Transformer1(transformer2io)a
中运行该字符串,那么我们可以lift(lift getLine)
举起
如果导入Control.Monad.Trans.Class
,则可以提升ReaderT操作。例如,lift(asks…
而不仅仅是asks…
这确实很有帮助。您评论的错误可能是由于在checkHitR
中使用了asks
还有一个类型错误
进行起吊后,我们发现错误:
frosch.hs:23:5: error:
• Couldn't match type ‘()’ with ‘Int’
Expected type: MSF (GameEnv m) () Ball
Actual type: MSF
(WriterT [[Char]] (ReaderT GameSettings m)) () ()
这是因为您的checkHitR
没有返回值rp
(我认为应该返回)。解决该问题将为我们提供以下最终代码:
module Main where
import FRP.BearRiver
import Control.Monad.Trans.Class
import Control.Monad
import Control.Monad.Trans.MSF.Reader
import Control.Monad.Trans.MSF.Writer
type Game = Ball
type Ball = Int
type GameEnv m =
WriterT [String] (ReaderT GameSettings m)
data GameSettings
= GameSettings
{ leftPlayerPos :: Int
, rightPlayerPos :: Int
}
ballToRight :: Monad m => MSF (GameEnv m) () Ball
ballToRight =
count >>> arrM addLeftPlayerPos >>> arrM checkHitR
where
addLeftPlayerPos =
(\n -> (n +) <$> lift (asks leftPlayerPos))
checkHitR n = do
rp <- lift (asks rightPlayerPos)
when (rp > n) $ tell ["Ball is at " ++ (show n)]
pure rp
modulemain其中
比尔河进口玻璃钢
导入控制.Monad.Trans.Class
进口管制
导入控制.Monad.Trans.MSF.Reader
导入控制.Monad.Trans.MSF.Writer
类型游戏=球
类型Ball=Int
GameEnv m型=
WriterT[String](ReaderT游戏设置m)
数据游戏设置
=游戏设置
{leftPlayerPos::Int
,rightPlayerPos::Int
}
ballToRight::Monad m=>MSF(GameEnv m)()Ball
棒球=
计数>>>arrM addLeftPlayerPos>>>arrM校验器
哪里
addLeftPlayerPos=
(\n->(n+)抬起(询问左玩家))
checkhitrn=do
rp n)$tell[“球在”++(显示n)]
纯rp
您能提供您尝试的实现和错误吗?当然,我的实现只是我添加到帖子中的错误消息where子句中的一个。此外,我将相关部分添加到了中。您是否尝试提升(询问leftPlayerPos)
?我还没有测试过,但这是在变压器下面使用monad的正常方式。当然,但这没有多大帮助:•无法将类型“ReaderT GameSettings m2”与“WriterT[String](ReaderT GameSettings m)
匹配。。。也就是说:预期类型:MSF(GameEnv m)()Ball
而不是实际类型:MSF(ReaderT GameSettings m2)(
frosch.hs:23:5: error:
• Couldn't match type ‘()’ with ‘Int’
Expected type: MSF (GameEnv m) () Ball
Actual type: MSF
(WriterT [[Char]] (ReaderT GameSettings m)) () ()
module Main where
import FRP.BearRiver
import Control.Monad.Trans.Class
import Control.Monad
import Control.Monad.Trans.MSF.Reader
import Control.Monad.Trans.MSF.Writer
type Game = Ball
type Ball = Int
type GameEnv m =
WriterT [String] (ReaderT GameSettings m)
data GameSettings
= GameSettings
{ leftPlayerPos :: Int
, rightPlayerPos :: Int
}
ballToRight :: Monad m => MSF (GameEnv m) () Ball
ballToRight =
count >>> arrM addLeftPlayerPos >>> arrM checkHitR
where
addLeftPlayerPos =
(\n -> (n +) <$> lift (asks leftPlayerPos))
checkHitR n = do
rp <- lift (asks rightPlayerPos)
when (rp > n) $ tell ["Ball is at " ++ (show n)]
pure rp