16

我正在关注这个博客,在 haskell 中编写一个简单的 http 服务器,

>>>我不清楚的用法。这个代码片段有什么作用?

handleHttpConnection r c = runKleisli
    (receiveRequest >>> handleRequest r >>> handleResponse) c >>
    close c

在此链接上类似,我看到了<<<

let h =     arr (++ "!")
          <<< arr foo
          <<< Kleisli bar
          <<< arr id

做什么<<<>>>做什么?(黑客文档非常简洁,不能从中得到太多。)

4

1 回答 1

21

正如 Hackage 和/或 Hoogle 会告诉你的那样,

(>>>) :: Category k => a`k`b  -> b`k`c  -> a`k`c
(<<<) :: Category k => b`k`c  -> a`k`b  -> a`k`c

观察到后者实际上是一样的

(.)   :: Category k => b`k`c  -> a`k`b  -> a`k`c

或者,以它的Prelude形式,专门用于Hask类别的函数,

(.)   ::               (b->c) -> (a->b) -> (a->c)

所以,<<<简单>>>地组合函数,或更一般地说态射/箭头。

<<<与熟悉的方向相同.,同时>>>翻转参数以使“数据从左向右流动”。


现在,对于Hask以外的类别,箭头组合的含义当然取决于类别。是一个容易理解的例子:假设我们有一个纯函数Kleisli IO

pipe :: Double -> String
pipe = show . sqrt . (+2) . abs

正如我所说,这也可以写成

pipe = abs >>> (+2) >>> sqrt >>> show

现在,如果您想添加原始 IO 日志记录(就像您可能使用命令式语言一样),您可以引入

type (-|>) = Kleisli IO

abs', add2', sqrt' :: Num a => a -|> a
show' :: Show a => a -|> String

abs'  = Kleisli $ \x -> do putStrLn ("Absolute of "++show x++"...")
                           return $ abs x
add2' = Kleisli $ \x -> do putStrLn ("Add 2 to "++show x++"...")
                           return $ x + 2
sqrt' = Kleisli $ \x -> do putStrLn ("Square root of "++show x++"...")
                           return $ sqrt x
show' = Kleisli $ \x -> do putStrLn ("Show "++show x++"...")
                           return $ show x

有了它,你可以定义

pipe' :: Double -|> String

以与以前完全相同的方式,即

pipe' = abs' >>> add2' >>> sqrt' >>> show'

但是您现在将打印出中间结果作为副作用。

于 2015-07-05T08:38:33.653 回答