Difference between revisions of "関数"

From HaskellWiki
Jump to navigation Jump to search
 
Line 30: Line 30:
 
この関数は2つの引数をとります:"f"という"a"から"b"へ写像する関数と、"a"のリスト"xs"です。返り値は"b"のリストで、これは"xs"の中のすべての要素に"f"を適用した結果のリストになります。したがって、<hask>map square [1,1,2,3,5,8]</hask>は<hask>[1,1,4,9,25,64]</hask>というリストを返します。"map"が返した”b”のリストが関数のリストにもなりえると気づくと、だんだん面白くなってきます。
 
この関数は2つの引数をとります:"f"という"a"から"b"へ写像する関数と、"a"のリスト"xs"です。返り値は"b"のリストで、これは"xs"の中のすべての要素に"f"を適用した結果のリストになります。したがって、<hask>map square [1,1,2,3,5,8]</hask>は<hask>[1,1,4,9,25,64]</hask>というリストを返します。"map"が返した”b”のリストが関数のリストにもなりえると気づくと、だんだん面白くなってきます。
   
  +
あるデータ構造(たとえば"Set")があったとして、関数<hask>insert :: Int -> Set -> Set</hask>があったとします。この関数は整数と集合を引数にとり、引数に与えた整数を引数に与えた集合に挿入してできた新しい集合を返します。そして、"mySet"と"myList"があるとして、それぞれ集合の中に集合やリストがあります。整数のリストを再帰的に要素1つづつ"myList"に挿入するような関数も書けますが、ファーストクラス関数を使えばもっと簡単に書けます。<hask>map insert myList</hask>という式を見てください。--この式が生成するリストの型はなんでしょうか?"insert"は"Int"と"Set"を引数にとりますが、"Int"しか与えられていませんので、結果のリストは集合を引数にとって、集合を返す関数のリストになっています。イメージとしては、コード<hask>map insert [1,2,3]</hask>はリスト<hask>[(insert 1) (insert 2) (insert3)]</hask>を返します。
Suppose you have some data structure (e.g. ''Set'') that has the function <hask>insert :: Int -> Set -> Set</hask>, which takes an integer and a set, and returns the set created by inserting the given integer into the given set. And suppose you have ''mySet'' and ''myList,'' a set and a list of values to be added to the set, respectively. One could write a function to recurse over the list of integers, each time inserting a single member of ''myList,'' but with first-class functions this is not necessary. Look at the expression <hask>map insert myList</hask> -- what is the type of the list which it produces? Since ''insert'' takes an ''Int'' and a ''Set'', but only ''Int''s were given, the resulting list will be of functions that take a set and return a set. Conceptually, the code <hask>map insert [1,2,3]</hask> will return the list <hask>[(insert 1) (insert 2) (insert 3)]</hask>.
 
   
===Composition / folding example===
+
===合成 / 畳み込みの例===
Haskell supports a [[Function composition]] operator:
+
Haskellでは[[Function composition]]演算子をサポートしています:
 
<haskell>
 
<haskell>
 
(.) :: (b -> c) -> (a ->b) -> (a->c)
 
(.) :: (b -> c) -> (a ->b) -> (a->c)
 
(f . g) x = f (g x)
 
(f . g) x = f (g x)
 
</haskell>
 
</haskell>
So, for example, <hask>((insert 1) . (insert 2) . (insert 3)) mySet</hask> is the same as <hask>insert 1 (insert 2 (insert 3 mySet))</hask>. We're almost there -- what we need now is a function that can automatically put the composition operator between every element of <hask>map insert myList</hask>. Such code is included in Haskell, and it's known as ''folding.''
+
たとえば、<hask>((insert 1) . (insert 2) . (insert 3)) mySet<hask><hask> insert 1 (insert 2 (inesrt 3 mySet))</hask>と同じ意味です。すると、先の章の例を考えれば、もう一息のところまで来ています。--いま必要なのは自動的に合成演算子を<hask>map insert myList<hask>のそれぞれの要素の間におくことです。Haskellではそれを可能にするコードがあります。それが"畳み込み(folding)"として知られているものです。
   
  +
"fold"関数はいくつかの種類がありますが、基本的な概念としては同じです。関数とリストが与えられて、リストのすべての要素の"間に"関数を適応させてリストを"折り畳む"イメージです。簡単な二項演算子で考えてみるのが一番簡単ですが、実際使うときは他の関数でもなんら代わりはありません。たとえば<hask>foldr1 (+) [1,1,2,3,5]</hask>は結果として<hask>1+1+2+3+5</hask>という式を生成します。したがって12が返ってきます。集合の例では<hask>foldr1 (.) (map insert myList)</hask>は先程我々がほしがっていたものを与えてくれます。つまり、連続して”myList"に要素を挿入してくれるわけです。この式の型はどうなっているのでしょうか?答えは<hask>Set -> Set</hask>です。つまり集合を引数に取り、集合を返すわけです。--この例では返り値の集合は"myList"のすべての要素が挿入されたものになります。例を完成させると、
Several variants of the ''fold'' function are defined, but the basic concept is the same: given a function and a list, "collapse" the list by applying the function "between" its elements. This is easiest to see with simple binary operators, but it is not limited to them. For example, <hask>foldr1 (+) [1,1,2,3,5]</hask> eventually creates the expression <hask>1+1+2+3+5</hask>, and thus returns 12. In the set example, <hask>foldr1 (.) (map insert myList)</hask> gives us what we want, the successive insertion of every element of ''myList.'' What is the type of this expression? It is <hask>Set -> Set</hask>, meaning it will take a set and return a set -- in this case, the set it returns will have every element of ''myList'' inserted. To complete the example,
 
 
<haskell>
 
<haskell>
 
newSet = (foldr1 (.) (map insert myList)) mySet
 
newSet = (foldr1 (.) (map insert myList)) mySet
 
</haskell>
 
</haskell>
  +
は"newSet"を"mySet"に"myList"の要素が挿入されたものとして定義しています。
will define ''newSet'' as ''mySet'' with the elements of ''myList'' inserted.
 
   
==See also==
+
==参考==
* The [http://haskell.cs.yale.edu/tutorial/functions.html Functions section] in the Gentle Introduction.
+
* [http://haskell.cs.yale.edu/tutorial/functions.html Functions section] in the Gentle Introduction.
   
 
Languages: [[関数|ja]]
 
Languages: [[関数|ja]]

Latest revision as of 03:18, 6 December 2009

数学的に言えば、関数というのはという集合のすべての値をという値の集合に関連付けるものです。関数が整数なら、整数の集合の中にある全ての要素を他の集合--この場合整数の2乗の集合に対応させます。Haskellの関数は以下の例で表されます。付属的に type specification がコンパイラ(や利用しようとするプログラマ)に関数の使い方のヒントを与えます。

Examples

square :: Int -> Int
square x = x * x

言い換えれば、関数というのは "入力" と "出力" を持っていて、入力からどのように出力を生成するかを記述したものといえます。関数は "適用する" ことができます。つまり単純に入力値を関数の引数として与えて、対応する出力値として受け取るということです。

Haskellの関数は "ファーストクラス" エンティティです。つまり

  • 名前が与えられる
  • ある式の値である
  • リストのメンバになれる
  • タプルの要素になれる
  • 関数の引数として与えられる
  • 関数の結果として返される

(Davieの "Introduction to Functional Programming Systems using Haskell."より引用)

map の例

ファーストクラス関数の威力を見られる例として、"map"関数を考えてみましょう。 map:

map :: (a -> b) -> [a] -> [b]
map f xs = [f x | x <- xs]

(これはHigher order functionであることを覚えていてください) この関数は2つの引数をとります:"f"という"a"から"b"へ写像する関数と、"a"のリスト"xs"です。返り値は"b"のリストで、これは"xs"の中のすべての要素に"f"を適用した結果のリストになります。したがって、map square [1,1,2,3,5,8][1,1,4,9,25,64]というリストを返します。"map"が返した”b”のリストが関数のリストにもなりえると気づくと、だんだん面白くなってきます。

あるデータ構造(たとえば"Set")があったとして、関数insert :: Int -> Set -> Setがあったとします。この関数は整数と集合を引数にとり、引数に与えた整数を引数に与えた集合に挿入してできた新しい集合を返します。そして、"mySet"と"myList"があるとして、それぞれ集合の中に集合やリストがあります。整数のリストを再帰的に要素1つづつ"myList"に挿入するような関数も書けますが、ファーストクラス関数を使えばもっと簡単に書けます。map insert myListという式を見てください。--この式が生成するリストの型はなんでしょうか?"insert"は"Int"と"Set"を引数にとりますが、"Int"しか与えられていませんので、結果のリストは集合を引数にとって、集合を返す関数のリストになっています。イメージとしては、コードmap insert [1,2,3]はリスト[(insert 1) (insert 2) (insert3)]を返します。

合成 / 畳み込みの例

HaskellではFunction composition演算子をサポートしています:

(.) :: (b -> c) -> (a ->b) -> (a->c)
(f . g) x = f (g x)

たとえば、((insert 1) . (insert 2) . (insert 3)) mySet<hask><hask> insert 1 (insert 2 (inesrt 3 mySet))と同じ意味です。すると、先の章の例を考えれば、もう一息のところまで来ています。--いま必要なのは自動的に合成演算子をmap insert myList<hask>のそれぞれの要素の間におくことです。Haskellではそれを可能にするコードがあります。それが"畳み込み(folding)"として知られているものです。 "fold"関数はいくつかの種類がありますが、基本的な概念としては同じです。関数とリストが与えられて、リストのすべての要素の"間に"関数を適応させてリストを"折り畳む"イメージです。簡単な二項演算子で考えてみるのが一番簡単ですが、実際使うときは他の関数でもなんら代わりはありません。たとえば<hask>foldr1 (+) [1,1,2,3,5]は結果として1+1+2+3+5という式を生成します。したがって12が返ってきます。集合の例ではfoldr1 (.) (map insert myList)は先程我々がほしがっていたものを与えてくれます。つまり、連続して”myList"に要素を挿入してくれるわけです。この式の型はどうなっているのでしょうか?答えはSet -> Setです。つまり集合を引数に取り、集合を返すわけです。--この例では返り値の集合は"myList"のすべての要素が挿入されたものになります。例を完成させると、

newSet = (foldr1 (.) (map insert myList)) mySet

は"newSet"を"mySet"に"myList"の要素が挿入されたものとして定義しています。

参考

Languages: ja