2013-03-27 5 views
8

最初のインスタンスを宣言します。中にエラーが発生しました:私はそれらを使用するいくつかの簡単な関数を書くことにより、Haskellでは<em>ラムダ関数</em>(すなわち<em>無名関数</em>)を理解しようとしています

次の例では、3つのパラメータを取り込み、3つのうち2つを匿名関数を使用して追加し、その後に3つ目のパラメータを追加しようとしています。 最初にインスタンスを宣言しなければならないというエラーが表示されます。

specialAdd x y z = (\x y -> x + y) + z 

私は私の例が機能しない理由のいずれかの説明および/または私はより良いラムダ関数を理解するのに役立つであろう任意の説明を感謝しています。ここで

+2

(\ XY - > X + Y)::のNum A => A - > A - > a 関数にzを追加しようとしています – Vladimir

答えて

16

specialAdd x y z = (\x y -> x + y) + z

、何をやろうとしていることは仕事に行くされていない番号に機能を追加することです。 (\x y -> x + y) + zを見てください:a + bという形です。このような式が機能するには、a部分とb部分は同じ型の数字でなければなりません。

ハスケルは珍しい言語ですので、そのエラーメッセージはほとんど「あなたはできません」という形式です。ここで何が起きているのは、(\x y -> x + y)が関数であるとみなし、a + bのような式ではbaと同じ型でなければならないので、bも関数でなければならないと結論づけます。 Haskellでは、組み込み型以外の型を追加する独自の規則を定義することもできます。 「2つの関数を追加することはできません」というエラーを表示するだけではなく、「2つの関数を追加できるルールを定義していません」というエラーが表示されます。次

は、あなたがやりたいことになります。

ここ
specialAdd x y z = ((\x y -> x + y) x y) + z 

あなたはzに結果を追加し、その後、引数xyに機能(\x y -> x + y)を適用しています。

1

あなたが何かとして(+)使用しようとしています(Num a) => (a -> a -> a) -> a -> ??のように正しくありません。

(+)はクラスNumで定義され、(a - > a - > a)はこのクラスのインスタンスではありません。

正確に達成しようとしているのは何ですか?

10

匿名関数を実行する良い方法は、高次関数をfoldまたはmapとして使用することです。エントリーポイントとしてマップを使用して

マップの

基本的な定義、例造り上げ

map f [] = [] 
map f (x:xs) = f x : f xs 

>>> let list = [0..4] 
>>> let f x = x + 1 

我々が得るマップを適用すると、

>>> map f list 
[1,2,3,4,5] 

ここで、t彼のfの宣言と匿名関数を使用してそれを置き換える、

>>> map (\x->x+1) list 
[1,2,3,4,5] 

が、我々はこのように

f = \x-> x + 1 --- The same as f x = x + 1, but this is the equivalent lambda notation. 

写像fリスト==マップ(\ x軸> X + 1)リストを推定その後、簡単な関数から始めて、無名関数に変換する方法と、無名関数がラムダ抽象に依存する方法を見ていきます。

練習として、f x = 2 * xを翻訳しようとします。

>>> foldl' (\x y -> x + y) 0 [0..4] 

が再び平等を使用して、として

今より複雑に、再び実施例2つの引数、

を取る無名関数、

>>> let add x y = x + y 
>>> foldl' add 0 [0..4] 
10 

は、匿名関数を使用して書き換えることができます私たちは、add = \ xy - > x + y
のように推論します。hakellの場合と同様に、すべての関数は1つの引数の関数であり、部分的に適用すると、以前の無名関数をadd = \ x - >(\ y - > x + y)として書き直すことができます。

次にトリックはどこですか?なぜなら、高次の関数には無名関数の使用を示しており、これからラムダ表記法を使って関数を書き直す方法を示しています。私はそれが匿名関数を書き留める方法を学ぶのを助けることができるのですか?

単に高次機能を使用して既存のフレームワークを提供しています。
このフレームワークは、この表記であなたを収容する大きな機会です。
これから始めて、無限の範囲の運動を推論することができます。たとえば、次のようにします。

A - Find the corresponding anonymous function ? 

1 - let f (x,y) = x + y in map f [(0,1),(2,3),(-1,1)] 
2 - let f x y = x * y in foldl' f 1 [1..5] 

B - Rewrite all of them using lambda notation into a declarative form (f = \x-> (\y-> ...) 

などなど....


(F0) f x1 x2 ... xn = {BODY of f} 

として

関数は常に

(F1) f = \x1 x2 ... xn -> {BODY of f} 
、と書き換えることができ、要約すると

(F2) (\x1 x2 ... xn -> {BODY of f}) 

F2の形だけで無名関数、ラムダ計算書への機能の純粋な翻訳です

。 F1は宣言的なラムダ表記法です(fを宣言していますので、匿名F2にバインドしています)。 F0はHaskellerの通常の記法である。

最後の注記は、引数の間に括弧を入れることができるという事実に焦点を当て、これはクロージャを作成します。そのことは、関数の引数のサブセットを使って関数のコードのサブセットを完全に評価できることを意味します(自由変数がなくなる形式に変換することを意味します)が、別の話です。この例では

2

私はLabmbda/Anonymous関数が「インライン」関数を宣言し、名前を付ける必要がないことを理解しています。 "¥"(ギリシャ語の場合はASCII、λ)は、 " - >"の後に続く式の変数名に先行します。たとえば、

(\x y -> x + y) 

は(+)と同様の匿名(ラムダ)関数です。これは、タイプのNumの2つのパラメータを受け取り、その合計を返します:

Prelude> :type (+) 
(+) :: Num a => a -> a -> a 

Prelude> :type (\x y -> x + y) 
(\x y -> x + y) :: Num a => a -> a -> a 

他の人が指摘したように、ので、あなたの例では、\ XY(、それの右側にはラムダ関数を使用している、働いていない - > X + y)は、(+)演算子のパラメータとして使用されます。この演算子は、デフォルトでNum型のパラメータに対してのみ定義されます。ラムダ関数の美しさの中には、その "匿名の"使用法があります。 Vladimirは左辺から変数を渡すことで、宣言でラムダ関数を使用する方法を示しました。より "匿名の"使用は、関数に名前(したがって匿名)を与えることなく、単に変数を使って呼び出すことができます。例えば、

Prelude> (\x y z -> x + y + z) 1 2 3 
6 

and if you like writing parentheses: 

Prelude> (((+).) . (+)) 1 2 3 
6 

または(あなたの例の宣言のように)長い表現で、例えば、

Prelude> filter (\x -> length x < 3) [[1],[1,2],[1,2,3]] 
[[1],[1,2]] 
関連する問題

 関連する問題