2016-11-20 10 views
0

こんにちはStackOverflow!concatMapの説明

私はハスケルと仕事を始めて、concatMapの機能を見つけました。 私は、この言語にはかなり新しいですので、私は次のコードを理解するいくつかの問題(source)があります。私の知る限りconcatMapが関数の引数fに取る機能を理解するよう

concatMap f = cmap where 
    cmap [] = [] 
    cmap (x : xs) = accum (f x) where 
     accum [] = cmap xs 
     accum (y : ys) = y : accum ys 

を。

しかし、関数を別の関数に設定するにはどうすればよいですか? fの結果をcmapに設定していますか、fのパラメータとしてcmapを使用していますか?

助けていただければ幸いです。

ありがとうございます!

+3

そのコードは、初心者にはあまり馴染みのない、ポイントフリーのishで書かれています。'='の両側に 'ys'を追加します。 'concatMap f ys = cmap ys'です。また、 'concatMap f'の標準的な定義は' concat 'です。マップf '。 – Zeta

+2

私はおそらくもう少し行くとコードが混乱していると言う。私は 'cmap(x:xs)= f x ++ cmap xs'を使うのではなく、奇妙な' accum'関数を書かなければならない理由はありません。 – dfeuer

答えて

4

あなたが投稿したコードは、初心者のために非常に簡単ではありません。入力リストが空戻りcmap xsときさもなければy:ys上に第一出力要素としてy出射した後、再帰的、出力accum xsに進み、

accum [] = cmap xs 
accum (y : ys) = y : accum ys 

上記機能:幸いなことに、我々は、ピースによって片を書き換えることができます。したがって

accum zsは、単にzs内のすべての要素出力と、その後、cmap xsを継続します。

++は、リストの連結である
accum zs = zs ++ cmap xs 

:私たちは、そのように書き換えることができます。次のように我々はそれに応じて、全体のコードを書き換えることができ

concatMap f = cmap where 
    cmap [] = [] 
    cmap (x : xs) = f x ++ cmap xs 

我々はさらに書き換えることができるが

初心者にとってよりアクセス可能であるべき
concatMap f [] = [] 
concatMap f (x : xs) = f x ++ concatMap f xs 

通りです。もっと非公式上記の定義は、式を満たす:

concatMap f [x1,x2,...,xn] = 
    f x1 ++ f x2 ++ ... ++ f xn ++ [] 

だから、我々はconcatMapが何をするか見ることができます。すべてのリスト要素にfを適用し、すべてのリスト要素に対してfはリストを返す必要があります。そして、そのようなリストはすべて連結されます。例えば

concatMap (\x -> [1..x]) [3,1,2] = 
    [1,2,3] ++ [1] ++ [1,2] = 
    [1,2,3,1,1,2] 
+0

すばらしいが非常に詳細な回答ありがとう@chi 私は答えとしてマークしています。 – TheCoolFrood

3

カイの答えはどのようにconcatMap作品をカバーし、私はあなたの疑問の一つに、特に焦点を当てる:

しかし、どのように我々は別のものと同等の機能を設定することができますか?

ハスケルの関数は、ほかの値と同じように値です。

GHCi> foo = "foo" 

これは文字列であることを起こるfooの定義、次のとおりです。これはの定義です...同じように

GHCi> :t foo 
foo :: [Char] 
GHCi> putStrLn foo 
foo 

...

GHCi> add = (+) 

add、これは関数であることがあります。

GHCi> :t add 
add :: Num a => a -> a -> a 
GHCi> add 2 3 
5 

上記の定義では、値を定義していることを強調するために、addのいずれのパラメータも明示的に記述しませんでした。

GHCi> add x y = (+) x y 

(我々は通常、上記の定義の右辺を書くだろうかあるx + yは、(+) x y用の代替構文単に便利であることに注意してください。)

:しかし、これを行うには完全に罰金それをあります

定義を書くの別の方法は、最初のパラメータだけを言及する部分適用を利用しています:

GHCi> add x = (+) x 

我々がすることもでき、ちょうどのためにそれのため(そしておそらく何が起こっているかを明確にする)、WHERE句で別の定義に(+) xを移動...

GHCi> :{ 
GHCi| add x = plusX 
GHCi|  where 
GHCi|  plusX = (+) x 
GHCi| :} 

...と明示的に再び二番目のパラメータを記述します。

GHCi> :{ 
GHCi| add x = plusX 
GHCi|  where 
GHCi|  plusX y = (+) x y 
GHCi| :} 

plusXは、引数をとり、xに追加する関数です。 addは、引数がxであり、xに対応する関数plusXを返す関数です。 add 2 3(add 2) 3に相当)を実行すると、2番目の引数をaddにするのはこの2番目の関数です。

は今、あなたのconcatMap定義と上記の比較:

concatMap f = cmap where 
    cmap [] = [] 
    cmap (x : xs) = accum (f x) where 
     accum [] = cmap xs 
     accum (y : ys) = y : accum ys 

定義は、同様の方法でレイアウトされています。 cmapは、リストを取り、concatMapへの引数であるconcatMapを使用して、addx引数を使用したのと同じように、結果を返します。だから、

、それを合計する:

我々はCMAPに等しいFの結果を設定している、あるいは我々がfのパラメータとしてCMAPを使用していますか?

どちらもありません。 fを使用してcmapを定義し、次にこれを使用してconcatMapを全体として定義します。

+0

答えを@duplodeいただきありがとうございます。 「答え」と印を付けるために、私はχとあなたの答えのどちらかを選択しなければなりませんでした。私にとって、何が起きているのかを完全に理解するためには、あなたと私の両方の答えが必要でした。しかし、私はChiの答えをマークしました。これは、concatMapの機能の広範な概要を示しています。これは、他の人に役立つかもしれないが、この問題の助けを求めています。 しかし、私はあなたの努力をappriciate、それは私の多くを助けた! – TheCoolFrood

+0

@TheCoolFroodよろしくお願いします。私はそれが助けてうれしいです。 – duplode