所以我在玩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
(某些中间计算会变大)。(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
,但是翻转了。答案 0 :(得分:2)
您的运营商.|
在Data.Function
中已经以&
的身份存在。要使其无意义,可以使用>>>
中的Control.Arrow
,也可以颠倒所有内容的顺序,而仅使用.
。对于Monad m => m a -> (a -> b) -> m b
,您需要<&>
中的Data.Functor
。