- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 Haskell + Netwire 5 (+ SDL) 创建游戏。现在我正在处理输出部分,我想创建在某些游戏状态下读取并输出要在屏幕上位图传输的 SDL 表面的连线。
但是,问题是 SDL 表面包含在 IO
monad 中,因此创建此类表面的任何函数都必须具有类型 a -> IO b
。当然,arr
不会从 a -> m b
构造 Wire
。然而,由于连线的类型签名是 (Monad m, Monoid e) => Wire s e m a b
,它看起来很像 Kleisi Arrow,但我找不到合适的构造函数来制作这样的连线。
我是 FRP 和 Arrows 的新手,并且没有在 Haskell 中进行过很多编程,因此这可能不是实现图形输出的最佳方法。如果我从一开始就错了,请告诉我。
一些相关的 SDL 函数:
createRGBSurfaceEndian :: [SurfaceFlag] -> Int -> Int -> Int -> IO Surface
fillRect :: Surface -> Maybe Rect -> Pixel -> IO Bool
blitSurface :: Surface -> Maybe Rect -> Surface -> Maybe Rect -> IO Bool
flip :: Surface -> IO ()
此代码类型检查,但现在我尝试将其与 SDL 接口(interface)进行测试
wTestOutput :: (Monoid e) => Wire s e IO () SDL.Surface
wTestOutput = mkGen_ $ \a -> (makeSurf a >>= return . Right)
where
makeSurf :: a -> IO SDL.Surface
makeSurf _ = do
s <- SDL.createRGBSurfaceEndian [SDL.SWSurface] 800 600 32
SDL.fillRect s (Just testRect) (SDL.Pixel 0xFF000000)
return s
testRect = SDL.Rect 100 100 0 0
最佳答案
现在,在玩完 Arrows 之后,我将回答我自己的问题使用函数putStrLn
。它的类型为String -> IO ()
,即a -> m b
,因此该方法应该推广到所有 Kleisli 线。我还演示了如何驱动电线,结果非常简单。
整个代码是用 Literate Haskell 编写的,因此只需复制并运行即可。
首先,有一些 Netwire 5 库的导入
import Control.Wire
import Control.Arrow
import Prelude hiding ((.), id)
现在,这就是制作 Kleisli Wire 的核心。假设你有一个类型为 a -> m b
的函数需要将其提升到电线中。现在,请注意 mkGen_
具有类型mkGen_::Monad m => (a -> m (Either e b)) -> Wire s e m a b
因此,要使用 a -> m b
制作一条线,我们首先需要获取一个函数类型为a -> m(Either () b)
。请注意,Left 抑制了电线,而 Right 激活它,所以内部部分是 Either () b
而不是b () 之一
。实际上,如果您尝试后者,则会出现一个模糊的编译错误会告诉你以错误的方式得到这个。
要得到a -> m(Either () b)
,首先考虑如何得到m (Either () b)
from m b
,我们从 monad (mb),将其向右提升,然后返回到单子(monad) m。简而言之:mB >>= 返回 .对。
。由于我们这里没有值“mB”,所以我们创建一个 lambda 表达式来获取 a -> m (Either () b)
:
liftToEither :: (Monad m) => (a -> m b) -> (a -> m (Either () b))
liftToEither f = \a -> (f a >>= return . Right)
现在,我们可以制作 Kleisli 线:
mkKleisli :: (Monad m, Monoid e) => (a -> m b) -> Wire s e m a b
mkKleisli f = mkGen_ $ \a -> (f a >>= return . Right)
那么,让我们尝试一下规范的“hello, world”线路!
helloWire :: Wire s () IO () ()
helloWire = pure "hello, world" >>> mkKleisli putStrLn
现在主要功能来说明如何驱动线。笔记与 Control.Wire.Run 中的 testWire 源代码进行比较从 Netwire 库来看,没有使用 liftIO:外部程序对电线的内部工作原理一无所知。它只是步骤电线忽略了其中的内容。 也许
这个Just
意味着更好组合而不是使用关于 Kleisli Wires 的Nothing
? (没有双关语的意思!)
main = go clockSession_ helloWire
where
go s w = do
(ds, s') <- stepSession s
(mx, w') <- stepWire w ds (Right ())
go s' w'
现在代码来了。不幸的是 StackOverflow 不能很好地与 Literate Haskell 配合使用...
{-# LANGUAGE Arrows #-}
module Main where
import Control.Wire
import Control.Monad
import Control.Arrow
import Prelude hiding ((.), id)
mkKleisli :: (Monad m, Monoid e) => (a -> m b) -> Wire s e m a b
mkKleisli f = mkGen_ $ \a -> liftM Right $ f a
helloWire :: Wire s () IO () ()
helloWire = pure "hello, world" >>> mkKleisli putStrLn
main = go clockSession_ helloWire
where
go s w = do
(ds, s') <- stepSession s
(mx, w') <- stepWire w ds (Right ())
go s' w'
更新
感谢 Cubic 的灵感。 liftToEither
实际上可以写成,你猜对了,liftM
:
liftToEither f = \a -> liftM Right $ f a
mkKleisli f = mkGen_ $ \a -> liftM Right $ f a
关于haskell - Netwire 5 中的 Kleisli Arrow?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32745934/
我想知道是否有办法转List[Kleisli[Option, Int, Int]]至 Kleisli[Option, Int, List[Int]] . 特别是我的 kleisli 列表是这样形成的:
我遵循优秀书籍Reactive Domain Modeling的设计,我需要混合Kleisli不同类型: object CombinedKleisli { type User = String
在 scalaz Kleisli[M[_], A, B]是 A => M[B] 的包装器,这允许组合这些函数。例如,如果 M[_] monad 是我可以写的 Kleisli[M, A, B]和 Kle
在尝试使用 Haskell 定义从连接 channel 读取的无限循环时,我想到了使用单子(monad)的 Kleisli 组合折叠部分应用函数的无限列表的想法。这个想法似乎合理且简单,但我遇到了一个
我最近偶然发现了 Kleisli 的概念,我阅读的每个教程/链接/引用资料都通过以下结构激发了 Kleisli 的使用: 组合返回 monad 的函数 : f: a -> m[b]与 g: b ->
我有一个从 Railway oriented programming 复制的验证模块在我的应用程序中执行错误处理: type ErrorMessage = ErrorMessage of string
这是 kleisli 组合的常见实现: kleisli :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c kleisli = \f g x -> f
如何组合两个返回验证的函数?以下是我没有成功的尝试: scala> def f: Int => Validation[String, Int] = i => if(i % 2 == 0) Succes
看完这篇article我了解 >=> (Kleisli 箭头)只是组合函数的高阶函数,它返回“一元值”。例如: val f: A => M[B] = ... val g: B => M[C] = ..
我有一些方法的调用链,我通过 Kleisli 传递上下文。基本上我想将一个上下文传递给数据库访问层,但我想在两者之间的任何地方访问这个上下文。 以下示例完美运行。但我的问题是,我想访问 OrderSe
这是我之前 question 的后续 我们可以定义一个通过路径 (List[String], XmlNode) => Option[XmlNode] 查找 XML 节点的函数作为函数的组合 (Stri
给定一个方法 def f[A, B, C](a: A) : Kleisli[Future, B, C] = ??? 我需要一个使用 Option[A] 的组合器 我的第一次尝试是: def g[A,
我遵循了函数式和响应式(Reactive)建模一书中的设计原则。 因此所有服务方法都返回Kleisli。 问题是如何在这些服务上添加可更新缓存。 这是我当前的实现,是否有更好的方法(现有的组合器,更实
我不明白为什么 Demonbind1 的定义会产生一些编译器错误。它看起来像一个愚蠢的翻转,但不知何故.. {-# LANGUAGE GADTs #-} {-# LANGUAGE RankNTypes
检查 Kleisli 定义, in Cats, and Functional and Reactive Domain Modelling 但是我还不能理解它的用处。如果我们谈论组合 Monadic 函
尝试在 Scala 中为虚构的部分类型实现 Kleisli 类别(阅读 Bartosz Milewski 的“程序员的类别理论”,这是第 4 章的练习) object Kleisli { type
这个问题的灵感来自对我之前的 question 的反馈。 Scalaz 为函数 A => M[B] 提供了一个包装类 Kleisli[M[_], A, B] . 如果 M[_] 是一个半群,则 Kle
尝试在 Scala 中为虚构的部分类型实现 Kleisli 类别(阅读 Bartosz Milewski 的“程序员的类别理论”,这是第 4 章的练习) object Kleisli { type
这个问题的灵感来自对我之前的 question 的反馈。 Scalaz 为函数 A => M[B] 提供了一个包装类 Kleisli[M[_], A, B] . 如果 M[_] 是一个半群,则 Kle
我尝试用 Kotlin 编写 Kleisli 求幂: fun kleisli(n: Int, f: (A) -> B): (A) -> B = if (n == 1) f else { it ->
我是一名优秀的程序员,十分优秀!