понимание монадического списка, получающее значения от уровней, отличных от самого внутреннего - PullRequest
0 голосов
/ 17 сентября 2018

Рассмотрите следующий очень простой пример использования монады массива и сделайте запись в качестве понимания списка или эквивалента для вложенного цикла:

one :: String
one = joinWith "\n" $ do
  n <- [ "1", "2" ]
  x <- [ "a", "b" ]
  y <- [ "A", "B" ]
  pure $ n <> x <> y

-- this generates a string like:

1aA
1aB
1bA
1bB
2aA
2aB
2bA
2bB

Теперь представьте, что вы бы предпочли иметь некоторые заголовки и отступы вваш вывод, например, так:

numbers
 lowers
  uppers
   1aA
   1aB
  uppers
   1bA
   1bB
 lowers
   uppers
   2aA
   2aB
 uppers
   2bA
   2bB

Вот модификация, которая выдала бы приведенную выше строку:

two :: String
two = joinWith "\n" $ ["numbers"] <> do
  n <- [ "1", "2" ]
  pure $ joinWith "\n" $ [" lowers"] <> do
    x <- [ "a", "b" ]
    pure $ joinWith "\n" $ ["  uppers"] <> do
      y <- [ "A", "B" ]
      pure $ "   " <> n <> x <> y

Это уже не так красиво и читабельно, и если все становится сложнее, чемв этом упрощенном примере было бы неплохо иметь лучший способ выразить это.

Следующий псевдокод может дать представление о том, что я имею в виду:

three :: String
three = joinWith "\n" $ do
  yield "numbers"
  n <- [ "1", "2" ]
  yield " lowers"
  x <- [ "a", "b" ]
  yield "  uppers"
  y <- [ "A", "B" ]
  yield $ "   " <> n <> x <> y

Это выглядит такболее разумный DSL для этого.Я пытался найти реализацию для этого, но не удалось.Я изучил монаду Writer, а также концепцию преобразователей монад, потому что я думал, что каким-то образом монаду List / Array нужно объединить с монадой Writer, но я не смог найти решение.

Как бы высделать это?

...