2010-02-27 19 views
2

我很好奇,是否有可能在Haskell中動態構建列表理解。動態構建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仍然很陌生,所以我可能忽略了一些明顯的東西。這甚至有可能嗎?

回答

11

名單單子的魔力:

 
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]]。但是,comprehensionsmonads故意相似。標準Prelude有sequence :: Monad m => [m a] -> m [a],當m是列表monad []時,它實際上就是我們上面寫的。

作爲另一種捷徑,mapM :: Monad m => (a -> m b) -> [a] -> m [b]僅僅是sequencemap的組合。

對於每個基地的不同權力的每個內部列表,您希望將它們乘以一個單一的數字。你可以寫這個遞歸

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已經被定義!我喜歡這種語言☺☺☺

+0

'讓權力(a,b)= [a^n | n < - [0 .. b-1]]' – Tordek 2010-02-27 21:42:09

+0

@Tordek謝謝,我原汁原味了一下。 – ephemient 2010-02-27 22:30:00

+0

美麗,謝謝。 – ezpz 2010-02-27 22:48:20