添加操作而不将结果更改为重构标记

amo*_*ebe 7 refactoring haskell pointfree do-notation

我想在Haskell中依次组合两个monad动作,丢弃第二个动作产生的任何值,并将参数传递给两个动作.目前我正在使用这样的do-block:

ask = do
  result <- getLine
  putStrLn result
  return result
Run Code Online (Sandbox Code Playgroud)

我本来希望写一点免费和整洁,所以我尝试了这个:

ask' = getLine <* putStrLn
Run Code Online (Sandbox Code Playgroud)

但是,这甚至不进行类型检查,问题是<*不会将第一个动作的结果传递给第二个动作.我希望将操作链接起来>>=,但不会更改结果.类型应该是(a -> m b) -> (a -> m c) -> (a -> m b),但Hoogle没有产生合适的结果.实现此功能组合的操作员是什么?

lef*_*out 8

作为一种趋势,如果你在两个不同的地方使用一个值,那么在一个明确的块中给它起一个名字可能一个好主意do,而不是按下毫无意义的风格.

将信息流分解为不同动作的抽象概念由笛卡尔幺半群类别捕获,Haskellers将其称为箭头.在您的情况下,您基本上是在IOKleisli类别中工作:

import Prelude hiding (id)
import Control.Arrow

ask' :: Kleisli IO () String
ask' = Kleisli (\()->getLine) >>> (putStrLn &&& id) >>> arr snd
Run Code Online (Sandbox Code Playgroud)

我不认为编写这样的代码是个好主意.