14
でリスト内包

この式ですることができます私のunsugarリスト内包:糖衣構文を削除:Haskellの

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

は、これが出力されます。

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

どのように、私はできそうにマップ、フィルタととそのコードを書いてください。

編集

ここ他:

[(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)] 

答えて

23

リスト内包(実際には、モナドの内包表記)は、doの表記にすることができます。いつものように脱糖することができ

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

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

よくa >>= \x -> return bfmap (\x -> b) aと同じであることが知られています。そう中間脱糖のステップ:

[1..4] >>= \i -> 
fmap (\j -> (i,j)) [i+1..4] 
リストについて

(>>=) = flip concatMap、及びfmap = 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] 

これは、強烈な答えで巻き上げる方法です。


第二は、同様に脱糖することができます別の変換方式はまだあり

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

回答ありがとうございます:) – Carlochess

2

脱糖コードは:

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

伊藤剛の答えにリファクタリングできるものはどれですか?

2

、それは私の知る限り、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で平らに取得する必要があります最も内側のレベルでのシングルトンリストの不要な建設を回避することができます。

関連する問題