我试图跟随this paper进行功能反应式编程,但我仍然坚持第4.2节中的第二个例子。
我得到了第一个启动并运行阅读器变换器的示例:
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)
但是下一步我正在努力。我无法弄清楚如何正确引入编写器转换器,因为我甚至无法编译:
module Main where
import FRP.BearRiver
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 +) <$> asks leftPlayerPos)
checkHitR n = do
rp <- asks rightPlayerPos
when (rp > n) $ tell ["Ball is at " ++ (show n)]
实际上函数调用addLeftPlayerPos
的行是有问题的,因为函数arrM addLeftPlayerPos
没有在论文中给出,我的版本似乎缺少WriterT
类型签名作为别名type GameEnv m ...
建议
什么可能正确实施addLeftPlayerPos
功能?
编辑:编译器错误是:
Expected type: MSF (GameEnv m) () Ball
Actual type: MSF (ReaderT GameSettings m1) () ()
• In the expression:
count >>> arrM addToLeftPlayerPos >>> arrM checkHitR
当你有一个变压器堆栈时,你必须“提升”你的操作来运行内部monad函数。例如:
type MyMonad a = Transformer1 (Transformer2 IO) a
这里的堆栈是IO的Transformer2的Transformer1。 “外部”monad是Transformer1,它将Transformer2与IO的内部(或底部,底部)monad包装在一起。在你的情况下,堆栈实际上是一个不知名的monad m
读者的作家,一切都很好。
现在,如果我们想要在函数qazxsw poi中运行qazxsw poi,我们必须f :: Transformer2 IO a
。同样,如果我们有g :: MyMonad
并且我们希望从lift f
内部运行那么我们可以getLine :: IO String
。
如果您导入g :: Transformer1 (Transformer2 IO) a
,您可以解除ReaderT操作。例如lift (lift getLine)
而不仅仅是Control.Monad.Trans.Class
。
这确实有很大帮助。您评论的错误可能是由于在lift (asks ...)
中使用asks ...
。
完成提升后我们有错误:
asks
这是因为你的checkHitR
没有返回值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