Существует ли конвейерная монада? - PullRequest
0 голосов
/ 25 февраля 2019

Итак, я играю с функцией сопряжения Кантора и пытаюсь следовать формулам Википедии как можно ближе.

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 ужасна!

  • Нужны все эти парены, потому что у меня есть формулавложенный в вызов функции и свободная привязка (-) вложенная в жесткую привязку (/).
  • (и оба эти оператора не являются коммутативными, поэтому я должен быть осторожен.)

Q 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 (?)

Q 2. Я (намеренно) утверждал, чтов стиле псевдомонады.Может ли это быть блок do?

  • Сначала мне нужна монада.Я мог бы использовать Maybe или (Either e) - что было бы хорошо, потому что некоторые из этих функций являются частичными, и я должен использовать безопасную версию.
  • Тогда вместо z I 'd поставить return z.
  • Но переплет идет не так, как нужно.Вместо Monad m => m a -> (a -> m b) -> m b я хочу Monad m => m a -> (a -> b) -> m b.Это похоже на fmap, но перевернуто.
  • Я мог бы применить некоторый вид поднятия к функциям / операторам, но это затем затушевало бы арифметику с монадным слесарным делом.
  • Повторный синтаксис?

1 Ответ

0 голосов
/ 25 февраля 2019

Ваш оператор .| уже существует в Data.Function как &.Чтобы сделать его бессмысленным, вы можете либо использовать >>> из Control.Arrow, либо инвертировать порядок всего и просто использовать ..Для Monad m => m a -> (a -> b) -> m b вы хотите <&>, от Data.Functor.

...