【问题标题】:Removing syntactic sugar: List comprehension in Haskell删除语法糖:Haskell 中的列表理解
【发布时间】:2011-12-23 03:55:42
【问题描述】:

我可以在这个表达式中取消列表理解吗:

[(i,j) | i <- [1..4], j <- [i+1..4]]

这是输出:

[(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]

如何通过map、filter等写出那段代码?

编辑

这里是另一个:

[(i,j,k) | i <- [1..6], j <- [i+1..6],k <- [j+1..6]]

这是输出:

[(1,2,3),(1,2,4),(1,2,5),(1,2,6),(1,3,4),(1,3,5),(1,3,6),(1,4,5),(1,4,6),(1,5,6),(2,3,4),(2,3,5),(2,3,6),(2,4,5),(2,4,6),(2,5,6),(3,4,5),(3,4,6),(3,5,6),(4,5,6)]

【问题讨论】:

    标签: list haskell functional-programming list-comprehension lazy-evaluation


    【解决方案1】:

    列表推导(实际上是 Monad 推导)可以脱糖为 do 表示法。

    do i <- [1..4]
       j <- [i+1..4]
       return (i,j)
    

    可以像往常一样去糖:

    [1..4]   >>= \i ->
    [i+1..4] >>= \j ->
    return (i,j)
    

    众所周知a &gt;&gt;= \x -&gt; return bfmap (\x -&gt; b) a 相同。所以中间脱糖步骤:

    [1..4] >>= \i -> 
    fmap (\j -> (i,j)) [i+1..4]
    

    对于列表,(&gt;&gt;=) = flip concatMapfmap = map

    (flip concatMap) [1..4] (\i -> map (\j -> (i,j) [i+1..4])
    

    flip 只是切换输入的顺序。

    concatMap (\i -> map (\j -> (i,j)) [i+1..4]) [1..4]
    

    这就是你最终得到 Tsuyoshi 答案的方式。


    第二个可以类似地脱糖为:

    concatMap (\i ->
      concatMap (\j ->
        map       (\k ->
          (i,j,k))
        [j+1..6])
      [i+1..6])
    [1..6]
    

    【讨论】:

      【解决方案2】:
      concatMap (\i -> map (\j -> (i, j)) [i+1 .. 4]) [1 .. 4]
      

      【讨论】:

        【解决方案3】:

        脱糖代码为:

        concatMap (\i -> concatMap (\j -> (i, j) : []) [i+1..4]) [1..4]
        

        这可以重构为伊藤刚的回答。

        【讨论】:

          【解决方案4】:

          据我所知,还有另一种翻译方案,这要归功于 Wadler。

          这将给出:

          let
              lc_outer (x:xs) = let lc_inner (y:ys) = (x,y) : lc_inner ys
                                    lc_inner []     = lc_outer xs
                                in lc_inner [x+1.. 4]
              lc_outer [] = []
          in  lc_outer [1..4]
          

          这种翻译避免了在最内层不必要地构建单例列表,这些列表需要稍后使用 concatMap 进行展平。

          【讨论】:

            猜你喜欢
            • 2020-07-24
            • 2010-10-31
            • 2016-01-22
            • 2015-05-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-06-16
            相关资源
            最近更新 更多