单子列表理解产生的值不是最内部的一个

时间:2018-09-17 18:04:15

标签: purescript

考虑以下使用数组monad和do表示法作为列表理解或嵌套循环等效的非常简单的示例:

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 monad以及monad转换器的概念,因为我认为在某种程度上必须将List / Array monad与writer monad结合起来,但是我找不到解决方案。

您将如何做?

0 个答案:

没有答案