在 Haskell 中动态构建列表理解

标签 dynamic haskell list-comprehension

我很好奇是否可以在 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 的版本.我对 Haskell 还是很陌生,所以我可能忽略了一些明显的东西。这甚至可能吗?

最佳答案

列表 monad 的神奇之处:

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]

This probably deserves a bit more explanation.

You could have written your own

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]] .

然而,comprehensionsmonads故意相似。标准 Prelude 有 sequence :: Monad m => [m a] -> m [a] , 当 m是列表 monad [] ,它实际上和我们上面写的完全一样。

作为另一个快捷方式, 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 已经定义了!我喜欢这种语言☺☺☺

关于在 Haskell 中动态构建列表理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2349037/

相关文章:

C++ 类数组的神秘转移

haskell - 是否可以在编译时使用 GHC API 修改程序?

python - 如何以列表理解形式编写以下代码?

python - 列表外的 "list comprehension"样式语法?

css - 我可以动态调整 css 设置的 div 边框的高度吗?

c - 消息队列 - 动态消息大小 - C

objective-c - 动态分配数组( vector 实现的动态大小)

Haskell:重载签名并针对不同的输入类型返回不同的结果

haskell - 在路径上找不到名为 yesod 的可执行文件

haskell - 使用列表理解查找列表中的单个元素