有流水线Monad吗?

时间:2019-02-25 03:38:33

标签: haskell monads

所以我在玩Cantor pairing function,并尝试尽可能遵循维基百科的公式。

type N = Int

toCantor   :: (N, N) -> N
fromCantor :: N      -> (N, N)

toCantor (x, y) = (x + y) * (x + y + 1) `div` 2 + y
  • type N,以便以后可以轻松更改为Integer(某些中间计算会变大)。
  • 未经草率的形式,部分遵循wp,部分因此(fromCantor . toCantor) === id(toCantor . fromCantor) === id

再次跟随wp:

fromCantor z = (x, y)  where
     x = w - y
     y = z - t
     t = (w * w + w) `div` 2
     w = floor $ (sqrt (fromIntegral (z * 8 + 1)) - 1.0) / 2.0

这有效,除了w的公式很难看之外,一切都如此!

  • 它需要所有这些要素,因为我在函数调用中嵌套了一个公式,而在紧密绑定的(-)中嵌套了一个松散绑定的(/)
  • (而且这两个运算符都是不可交换的,因此我必须小心。)

问题1。是否有办法使该公式更美观/没有积分?

我看到公式从z开始并向外扩展。所以我可以流水线计算:

(.|) :: a -> (a -> b) -> b   -- pipelining
infixl 0 .|
x .| f = f x                 -- aka flip ($)

wP :: N -> N                 -- w with Pipelining
wP z =  z
     .| (* 8)
     .| (+ 1)
     .| fromIntegral
     .| sqrt
     .| subtract 1.0
     .| (/ 2.0)
     .| floor

这是现有技术吗? (.|)是拼写该操作的好方法-我想我已经把它看作是Lens运算符(?)

问题2。我已经(故意)将其布置为伪单声道样式。可能是一个do块吗?

  • 首先,我需要一个单子。我可以使用Maybe(Either e),这是一件好事,因为其中一些功能是部分功能,我应该使用安全版本。
  • 然后我放z而不是return z
  • 但是绑定的方向是错误的。我需要Monad m => m a -> (a -> m b) -> m b而不是Monad m => m a -> (a -> b) -> m b。看起来像fmap,但是翻转了。
  • 我可以对函数/运算符进行某种形式的提升,但随后会用monad plumbing掩盖该算法。
  • 可绑定的语法?

1 个答案:

答案 0 :(得分:2)

您的运营商.|Data.Function中已经以&的身份存在。要使其无意义,可以使用>>>中的Control.Arrow,也可以颠倒所有内容的顺序,而仅使用.。对于Monad m => m a -> (a -> b) -> m b,您需要<&>中的Data.Functor