2012-02-11 3 views
9

は、95ページの、「実世界Haskellのを」読む著者は例を提供します。関数は3つではなく4つの引数を取ります - なぜこれは壊れませんか?

myFoldl f z xs = foldr step id xs z 
    where step x g a = g (f a x) 

私の質問は:なぜ、このコードはコンパイルのでしょうか? foldrには3つの引数しかありませんが、ここでは4つを渡します:stepidxsz。 (合計が1を想定しているため)

例えば、これは動作しません:

sum filter odd [1,2,3] 

ではなく、私が書く必要があります。

sum $ filter odd [1,2,3] 

答えて

12

ここfoldrのタイプです:

Prelude> :t foldr 
foldr :: (a -> b -> b) -> b -> [a] -> b 

は、我々はそれが4引数の関数となる方法を見つけ出すことはできますか?やるだけやってみよう!

  1. 我々は二番目のパラメータ(b)としてそれをid :: d -> dを与えて、それでは、型にそれを置き換えてみましょうしている:Haskellでは

    (a -> (d -> d) -> (d -> d)) -> (d -> d) -> [a] -> (d -> d) 
    
  2. a -> a -> aが私たちを与える、a -> (a -> a)と同じです(括弧の最後のセットを削除する):

    (a -> (d -> d) -> (d -> d)) -> (d -> d) -> [a] -> d -> d 
    
  3. さんが簡素化させ、を代入しては(d -> dため(a -> (d -> d) -> (d -> d))f)のために、読みやすくするために:

    e -> f -> [a] -> d -> d 
    

だから我々ははっきり私たちは4引数の機能を構築してきたことがわかります!頭が痛い。ここ


は、n引数のFUNCからN + 1引数の関数を作成する簡単な例は次のとおり

Prelude> :t id 
id :: a -> a 

id 1つの引数の関数です。

Prelude> id id id id id 5 
5 

しかし、私はただ5つの引数を与えました!

+0

私はあなたが 'id id 5'をなぜ行うことができるのか分かりませんが、あなたはできません:' foo x = x + 1;バーy = y + 1; foo bar 1'? – drozzy

+4

@drozzy - 型と多型に関するすべてです。 'id :: a - > a'を取る:' a'に*任意の*型を代用することができます。しかし、 'foo'は制約があるため、異なる:' foo ::(Num a)=> a - > a'という数字が必要です。 'bar ::(Num a)=> a - > a'は' Num'型のインスタンスではないので、 'foo'の'(Num a) '制約を満足しません。 –

+2

@drozzyおそらく関数アプリケーションの結合性を明らかにすれば助けになるでしょう! 'id id 5'は '(id id)5 'として解析されます。つまり' id'を最初に引数として 'id'を与え、次に' id(id 5) '。 –

10

それが原因foldrがどのように多型のためです:

foldr :: (a -> b -> b) -> b -> [a] -> b 

ここでは、bを関数型にインスタンス化しました。それを01としましょう。、foldrのタイプは、(例えば)に特化したように

foldr :: (a -> (c -> c) -> (c -> c)) -> (c -> c) -> [a] -> c -> c 
+1

また、元の質問のニュートラルな要素はすでに関数 'id'であることを指摘することもできます。 – ShiDoiSi

9

foldrはわずか3つの引数

間違っかかります。 Haskellのすべての関数は、1つの引数をとり、正確に1つの結果を生成します。

foldr :: (a -> b -> b) -> b -> [a] -> b 

を参照してください、foldrは一つの引数(a -> b -> b)を取り、1件の結果生成:b -> [a] -> bを。あなたは、この表示された場合:

foldr step id xs z 

を、それがこのためだけの速記であることに注意してください:これはナンセンスである理由

((((foldr step) id) xs) z) 

これは説明する:

sum filter odd [1,2,3] 
(((sum filter) odd) [1,2,3]) 

sum :: Num a => [a] -> aは、その入力としてリストを取りますあなたはそれに機能を与えました。

関連する問題