代码之家  ›  专栏  ›  技术社区  ›  ezpz

在haskell中动态构建列表理解

  •  2
  • ezpz  · 技术社区  · 16 年前

    我很好奇能否在Haskell中动态地构建一个列表理解。

    例如,如果我有以下内容:

    all_pows (a,a') (b,b') = [ a^y * b^z | y <- take a' [0..], z <- take b' [0..] ]
    

    我得到我想要的

    *Main> List.sort $ all_pows (2,3) (5,3)
    [1,2,4,5,10,20,25,50,100]
    

    不过,我真正想要的是

    all_pows [(Int,Int)] -> [Integer]
    

    以便我能支持 N 不建立的参数对 n 的版本 all_pows . 我对哈斯克尔还是个新手,所以我可能忽略了一些显而易见的事情。这是可能的吗?

    1 回复  |  直到 16 年前
        1
  •  11
  •   ephemient    16 年前

    单子的魔力:

    ghci> let powers (a, b) = [a ^ n | n <- [0 .. b-1]]
    ghci> powers (2, 3)
    [1,2,4]
    ghci> map powers [(2, 3), (5, 3)]
    [[1,2,4],[1,5,25]]
    ghci> sequence it
    [[1,1],[1,5],[1,25],[2,1],[2,5],[2,25],[4,1],[4,5],[4,25]]
    ghci> mapM powers [(2, 3), (5, 3)]
    [[1,1],[1,5],[1,25],[2,1],[2,5],[2,25],[4,1],[4,5],[4,25]]
    ghci> map product it
    [1,5,25,2,10,50,4,20,100]
    ghci> let allPowers list = map product $ mapM powers list
    ghci> allPowers [(2, 3), (5, 3)]
    [1,5,25,2,10,50,4,20,100]
    

    这可能需要更多的解释。

    你可以自己写

    cartesianProduct :: [[a]] -> [[a]]
    cartesianProduct [] = [[]]
    cartesianProduct (list:lists)
      = [ (x:xs) | x <- list, xs <- cartesianProduct lists ]
    

    这样的话 cartesianProduct [[1],[2,3],[4,5,6]] 艾斯 [[1,2,4],[1,2,5],[1,2,6],[1,3,4],[1,3,5],[1,3,6]] .

    然而, comprehensions monads 有意相似。标准序曲有 sequence :: Monad m => [m a] -> m [a] 以及何时 m 单子是单子吗 [] 它实际上和我们上面写的完全一样。

    作为另一条捷径, mapM :: Monad m => (a -> m b) -> [a] -> m [b] 只是 sequence map .

    对于每个基的不同幂的内部列表,您需要将它们乘以一个数字。你可以递归地写这个

    product list = product' 1 list
      where product' accum [] = accum
            product' accum (x:xs)
              = let accum' = accum * x
                 in accum' `seq` product' accum' xs
    

    或者使用折叠

    import Data.List
    product list = foldl' (*) 1 list
    

    但实际上, product :: Num a => [a] -> a 已经定义!我喜欢这种语言