现在,在玩完 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
而不是
Either b ()
。实际上,如果你尝试后者,一个模糊的编译错误会告诉你以错误的方式得到它。
要获取a -> m (Either () b)
,首先考虑如何从 获取
m (Either () b)
,m b
我们从 monad (m b) 中提取值,将其提升到 Right,然后返回到 monad m。简而言之:
mB >>= return . Right
。由于我们这里没有值“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
现在是主要功能来说明如何驱动电线。请注意,与 Netwire 库中的testWire
in源代码相比the Control.Wire.Run
,没有使用 liftIO:外部程序对内部线路的工作方式一无所知。它只是踩着电线,而忽略了里面的东西。Maybe
这Just
意味着比使用Nothing
Kleisli Wires 更好的组合?(没有双关语!)
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