コードをあまりいじらずに評価順序を制御する方法をご存知ないですか?
例えばリストを集合と見立てて冪集合を作る関数powersetを以下の用に定義します
powerset :: [a] -> [[a]]
powerset [] = [[]]
powerset (x:xs) = one ++ other
where one = [(x:ys)|ys<-other]
other = powerset xs
これを用いて与えられた集合からn個取り出した組み合わせの集合のリストを作る関数
combinationsを定義すると、
combinations :: Int -> [a] -> [[a]]
combinations n xs = filter ((n==).length) $ powerset xs -- 1)
のように定義出来ます。しかしこれではpowersetがn個以上の要素を含むリストを生成してしまうように思えます。
それをさせない為には、
combinations 0 _ = [[]]
combinations _ [] = []
combinations n (x:xs) = one ++ other
where one = [(x:ys)|ys<-(combinations(n-1)xs)]
other = combinations n xs -- 2)
のように定義する必要があります。ここで1)のコードの評価順序をうまいこと制御できれば、
((n==).length)が集合の要素がn個を越えた時点でその集合を弾いてくれるようになり、
2)のように定義しなくても良くなると思うのです。